xref: /sqlite-3.40.0/src/insert.c (revision cc85b411)
1cce7d176Sdrh /*
2cce7d176Sdrh ** Copyright (c) 1999, 2000 D. Richard Hipp
3cce7d176Sdrh **
4cce7d176Sdrh ** This program is free software; you can redistribute it and/or
5cce7d176Sdrh ** modify it under the terms of the GNU General Public
6cce7d176Sdrh ** License as published by the Free Software Foundation; either
7cce7d176Sdrh ** version 2 of the License, or (at your option) any later version.
8cce7d176Sdrh **
9cce7d176Sdrh ** This program is distributed in the hope that it will be useful,
10cce7d176Sdrh ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11cce7d176Sdrh ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cce7d176Sdrh ** General Public License for more details.
13cce7d176Sdrh **
14cce7d176Sdrh ** You should have received a copy of the GNU General Public
15cce7d176Sdrh ** License along with this library; if not, write to the
16cce7d176Sdrh ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17cce7d176Sdrh ** Boston, MA  02111-1307, USA.
18cce7d176Sdrh **
19cce7d176Sdrh ** Author contact information:
20cce7d176Sdrh **   [email protected]
21cce7d176Sdrh **   http://www.hwaci.com/drh/
22cce7d176Sdrh **
23cce7d176Sdrh *************************************************************************
24cce7d176Sdrh ** This file contains C code routines that are called by the parser
25cce7d176Sdrh ** to handle INSERT statements.
26cce7d176Sdrh **
27*cc85b411Sdrh ** $Id: insert.c,v 1.8 2000/06/07 15:11:27 drh Exp $
28cce7d176Sdrh */
29cce7d176Sdrh #include "sqliteInt.h"
30cce7d176Sdrh 
31cce7d176Sdrh /*
32cce7d176Sdrh ** This routine is call to handle SQL of the following form:
33cce7d176Sdrh **
34cce7d176Sdrh **    insert into TABLE (IDLIST) values(EXPRLIST)
35cce7d176Sdrh **
36cce7d176Sdrh ** The parameters are the table name and the expression list.
37cce7d176Sdrh */
38cce7d176Sdrh void sqliteInsert(
39cce7d176Sdrh   Parse *pParse,        /* Parser context */
40cce7d176Sdrh   Token *pTableName,    /* Name of table into which we are inserting */
41cce7d176Sdrh   ExprList *pList,      /* List of values to be inserted */
425974a30fSdrh   Select *pSelect,      /* A SELECT statement to use as the data source */
43cce7d176Sdrh   IdList *pField        /* Field name corresponding to pList.  Might be NULL */
44cce7d176Sdrh ){
455974a30fSdrh   Table *pTab;          /* The table to insert into */
465974a30fSdrh   char *zTab;           /* Name of the table into which we are inserting */
475974a30fSdrh   int i, j, idx;        /* Loop counters */
485974a30fSdrh   Vdbe *v;              /* Generate code into this virtual machine */
495974a30fSdrh   Index *pIdx;          /* For looping over indices of the table */
505974a30fSdrh   int srcTab;           /* Date comes from this temporary cursor if >=0 */
515974a30fSdrh   int nField;           /* Number of columns in the data */
525974a30fSdrh   int base;             /* First available cursor */
535974a30fSdrh   int iCont, iBreak;    /* Beginning and end of the loop over srcTab */
54cce7d176Sdrh 
55cce7d176Sdrh   zTab = sqliteTableNameFromToken(pTableName);
56cce7d176Sdrh   pTab = sqliteFindTable(pParse->db, zTab);
57cce7d176Sdrh   sqliteFree(zTab);
58cce7d176Sdrh   if( pTab==0 ){
59cce7d176Sdrh     sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0,
60cce7d176Sdrh         pTableName->z, pTableName->n, 0);
61cce7d176Sdrh     pParse->nErr++;
62cce7d176Sdrh     goto insert_cleanup;
63cce7d176Sdrh   }
64cce7d176Sdrh   if( pTab->readOnly ){
65cce7d176Sdrh     sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
66cce7d176Sdrh         " may not be modified", 0);
67cce7d176Sdrh     pParse->nErr++;
68cce7d176Sdrh     goto insert_cleanup;
69cce7d176Sdrh   }
705974a30fSdrh   v = pParse->pVdbe;
715974a30fSdrh   if( v==0 ){
725974a30fSdrh     v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
735974a30fSdrh   }
745974a30fSdrh   if( v==0 ) goto insert_cleanup;
755974a30fSdrh   if( pSelect ){
765974a30fSdrh     int rc;
775974a30fSdrh     srcTab = pParse->nTab++;
785974a30fSdrh     sqliteVdbeAddOp(v, OP_Open, srcTab, 1, 0, 0);
795974a30fSdrh     rc = sqliteSelect(pParse, pSelect, SRT_Table, srcTab);
805974a30fSdrh     if( rc ) goto insert_cleanup;
815974a30fSdrh     assert( pSelect->pEList );
825974a30fSdrh     nField = pSelect->pEList->nExpr;
835974a30fSdrh   }else{
845974a30fSdrh     srcTab = -1;
855974a30fSdrh     assert( pList );
865974a30fSdrh     nField = pList->nExpr;
875974a30fSdrh   }
885974a30fSdrh   if( pField==0 && nField!=pTab->nCol ){
89cce7d176Sdrh     char zNum1[30];
90cce7d176Sdrh     char zNum2[30];
915974a30fSdrh     sprintf(zNum1,"%d", nField);
92cce7d176Sdrh     sprintf(zNum2,"%d", pTab->nCol);
93cce7d176Sdrh     sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
94cce7d176Sdrh        " has ", zNum2, " columns but ",
95cce7d176Sdrh        zNum1, " values were supplied", 0);
96cce7d176Sdrh     pParse->nErr++;
97cce7d176Sdrh     goto insert_cleanup;
98cce7d176Sdrh   }
995974a30fSdrh   if( pField!=0 && nField!=pField->nId ){
100cce7d176Sdrh     char zNum1[30];
101cce7d176Sdrh     char zNum2[30];
1025974a30fSdrh     sprintf(zNum1,"%d", nField);
103cce7d176Sdrh     sprintf(zNum2,"%d", pField->nId);
104cce7d176Sdrh     sqliteSetString(&pParse->zErrMsg, zNum1, " values for ",
105cce7d176Sdrh        zNum2, " columns", 0);
106cce7d176Sdrh     pParse->nErr++;
107cce7d176Sdrh     goto insert_cleanup;
108cce7d176Sdrh   }
109cce7d176Sdrh   if( pField ){
110cce7d176Sdrh     for(i=0; i<pField->nId; i++){
111cce7d176Sdrh       pField->a[i].idx = -1;
112cce7d176Sdrh     }
113cce7d176Sdrh     for(i=0; i<pField->nId; i++){
114cce7d176Sdrh       for(j=0; j<pTab->nCol; j++){
1157020f651Sdrh         if( sqliteStrICmp(pField->a[i].zName, pTab->aCol[j].zName)==0 ){
116cce7d176Sdrh           pField->a[i].idx = j;
117cce7d176Sdrh           break;
118cce7d176Sdrh         }
119cce7d176Sdrh       }
120cce7d176Sdrh       if( j>=pTab->nCol ){
121cce7d176Sdrh         sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
122cce7d176Sdrh            " has no column named ", pField->a[i].zName, 0);
123cce7d176Sdrh         pParse->nErr++;
124cce7d176Sdrh         goto insert_cleanup;
125cce7d176Sdrh       }
126cce7d176Sdrh     }
127cce7d176Sdrh   }
1285974a30fSdrh   base = pParse->nTab;
1295974a30fSdrh   sqliteVdbeAddOp(v, OP_Open, base, 1, pTab->zName, 0);
130bed8690fSdrh   for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
1315974a30fSdrh     sqliteVdbeAddOp(v, OP_Open, idx+base, 1, pIdx->zName, 0);
1325974a30fSdrh   }
1335974a30fSdrh   if( srcTab>=0 ){
1345974a30fSdrh     sqliteVdbeAddOp(v, OP_Rewind, srcTab, 0, 0, 0);
1355974a30fSdrh     iBreak = sqliteVdbeMakeLabel(v);
1365974a30fSdrh     iCont = sqliteVdbeAddOp(v, OP_Next, srcTab, iBreak, 0, 0);
137bed8690fSdrh   }
138cce7d176Sdrh   sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0);
139cce7d176Sdrh   if( pTab->pIndex ){
140cce7d176Sdrh     sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
141cce7d176Sdrh   }
142cce7d176Sdrh   for(i=0; i<pTab->nCol; i++){
143cce7d176Sdrh     if( pField==0 ){
144cce7d176Sdrh       j = i;
145cce7d176Sdrh     }else{
146cce7d176Sdrh       for(j=0; j<pField->nId; j++){
147cce7d176Sdrh         if( pField->a[j].idx==i ) break;
148cce7d176Sdrh       }
149cce7d176Sdrh     }
150cce7d176Sdrh     if( pField && j>=pField->nId ){
1517020f651Sdrh       char *zDflt = pTab->aCol[i].zDflt;
152c61053b7Sdrh       if( zDflt==0 ){
153c61053b7Sdrh         sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
154c61053b7Sdrh       }else{
1557020f651Sdrh         sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0);
156c61053b7Sdrh       }
1575974a30fSdrh     }else if( srcTab>=0 ){
1585974a30fSdrh       sqliteVdbeAddOp(v, OP_Field, srcTab, i, 0, 0);
159cce7d176Sdrh     }else{
160cce7d176Sdrh       sqliteExprCode(pParse, pList->a[j].pExpr);
161cce7d176Sdrh     }
162cce7d176Sdrh   }
163cce7d176Sdrh   sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0);
1645974a30fSdrh   sqliteVdbeAddOp(v, OP_Put, base, 0, 0, 0);
1655974a30fSdrh   /* sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0); */
166bed8690fSdrh   for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
167cce7d176Sdrh     if( pIdx->pNext ){
168cce7d176Sdrh       sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
169cce7d176Sdrh     }
170cce7d176Sdrh     for(i=0; i<pIdx->nField; i++){
171cce7d176Sdrh       int idx = pIdx->aiField[i];
172cce7d176Sdrh       if( pField==0 ){
173cce7d176Sdrh         j = idx;
174cce7d176Sdrh       }else{
175cce7d176Sdrh         for(j=0; j<pField->nId; j++){
176cce7d176Sdrh           if( pField->a[j].idx==idx ) break;
177cce7d176Sdrh         }
178cce7d176Sdrh       }
179cce7d176Sdrh       if( pField && j>=pField->nId ){
1807020f651Sdrh         char *zDflt = pTab->aCol[idx].zDflt;
181c61053b7Sdrh         if( zDflt==0 ){
182c61053b7Sdrh           sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
183c61053b7Sdrh         }else{
1847020f651Sdrh           sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0);
185c61053b7Sdrh         }
1865974a30fSdrh       }else if( srcTab>=0 ){
187*cc85b411Sdrh         sqliteVdbeAddOp(v, OP_Field, srcTab, idx, 0, 0);
188cce7d176Sdrh       }else{
189cce7d176Sdrh         sqliteExprCode(pParse, pList->a[j].pExpr);
190cce7d176Sdrh       }
191cce7d176Sdrh     }
192cce7d176Sdrh     sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nField, 0, 0, 0);
1935974a30fSdrh     sqliteVdbeAddOp(v, OP_PutIdx, idx+base, 0, 0, 0);
1945974a30fSdrh     /* sqliteVdbeAddOp(v, OP_Close, idx, 0, 0, 0); */
195cce7d176Sdrh   }
1965974a30fSdrh   if( srcTab>=0 ){
1975974a30fSdrh     sqliteVdbeAddOp(v, OP_Goto, 0, iCont, 0, 0);
1985974a30fSdrh     sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, iBreak);
199cce7d176Sdrh   }
200cce7d176Sdrh 
201cce7d176Sdrh insert_cleanup:
2025974a30fSdrh   if( pList ) sqliteExprListDelete(pList);
2035974a30fSdrh   if( pSelect ) sqliteSelectDelete(pSelect);
204cce7d176Sdrh   sqliteIdListDelete(pField);
205cce7d176Sdrh }
206