xref: /sqlite-3.40.0/src/insert.c (revision bed8690f)
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*bed8690fSdrh ** $Id: insert.c,v 1.3 2000/06/02 13:27:59 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 */
42cce7d176Sdrh   IdList *pField        /* Field name corresponding to pList.  Might be NULL */
43cce7d176Sdrh ){
44cce7d176Sdrh   Table *pTab;
45cce7d176Sdrh   char *zTab;
46*bed8690fSdrh   int i, j, idx;
47cce7d176Sdrh   Vdbe *v;
48cce7d176Sdrh 
49cce7d176Sdrh   zTab = sqliteTableNameFromToken(pTableName);
50cce7d176Sdrh   pTab = sqliteFindTable(pParse->db, zTab);
51cce7d176Sdrh   sqliteFree(zTab);
52cce7d176Sdrh   if( pTab==0 ){
53cce7d176Sdrh     sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0,
54cce7d176Sdrh         pTableName->z, pTableName->n, 0);
55cce7d176Sdrh     pParse->nErr++;
56cce7d176Sdrh     goto insert_cleanup;
57cce7d176Sdrh   }
58cce7d176Sdrh   if( pTab->readOnly ){
59cce7d176Sdrh     sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
60cce7d176Sdrh         " may not be modified", 0);
61cce7d176Sdrh     pParse->nErr++;
62cce7d176Sdrh     goto insert_cleanup;
63cce7d176Sdrh   }
64cce7d176Sdrh   if( pField==0 && pList->nExpr!=pTab->nCol ){
65cce7d176Sdrh     char zNum1[30];
66cce7d176Sdrh     char zNum2[30];
67cce7d176Sdrh     sprintf(zNum1,"%d", pList->nExpr);
68cce7d176Sdrh     sprintf(zNum2,"%d", pTab->nCol);
69cce7d176Sdrh     sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
70cce7d176Sdrh        " has ", zNum2, " columns but ",
71cce7d176Sdrh        zNum1, " values were supplied", 0);
72cce7d176Sdrh     pParse->nErr++;
73cce7d176Sdrh     goto insert_cleanup;
74cce7d176Sdrh   }
75cce7d176Sdrh   if( pField!=0 && pList->nExpr!=pField->nId ){
76cce7d176Sdrh     char zNum1[30];
77cce7d176Sdrh     char zNum2[30];
78cce7d176Sdrh     sprintf(zNum1,"%d", pList->nExpr);
79cce7d176Sdrh     sprintf(zNum2,"%d", pField->nId);
80cce7d176Sdrh     sqliteSetString(&pParse->zErrMsg, zNum1, " values for ",
81cce7d176Sdrh        zNum2, " columns", 0);
82cce7d176Sdrh     pParse->nErr++;
83cce7d176Sdrh     goto insert_cleanup;
84cce7d176Sdrh   }
85cce7d176Sdrh   if( pField ){
86cce7d176Sdrh     for(i=0; i<pField->nId; i++){
87cce7d176Sdrh       pField->a[i].idx = -1;
88cce7d176Sdrh     }
89cce7d176Sdrh     for(i=0; i<pField->nId; i++){
90cce7d176Sdrh       for(j=0; j<pTab->nCol; j++){
91cce7d176Sdrh         if( sqliteStrICmp(pField->a[i].zName, pTab->azCol[j])==0 ){
92cce7d176Sdrh           pField->a[i].idx = j;
93cce7d176Sdrh           break;
94cce7d176Sdrh         }
95cce7d176Sdrh       }
96cce7d176Sdrh       if( j>=pTab->nCol ){
97cce7d176Sdrh         sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
98cce7d176Sdrh            " has no column named ", pField->a[i].zName, 0);
99cce7d176Sdrh         pParse->nErr++;
100cce7d176Sdrh         goto insert_cleanup;
101cce7d176Sdrh       }
102cce7d176Sdrh     }
103cce7d176Sdrh   }
104cce7d176Sdrh   v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
105cce7d176Sdrh   if( v ){
106cce7d176Sdrh     Index *pIdx;
10758b9576bSdrh     sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0);
108*bed8690fSdrh     for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
109*bed8690fSdrh       sqliteVdbeAddOp(v, OP_Open, idx, 1, pIdx->zName, 0);
110*bed8690fSdrh     }
111cce7d176Sdrh     sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0);
112cce7d176Sdrh     if( pTab->pIndex ){
113cce7d176Sdrh       sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
114cce7d176Sdrh     }
115cce7d176Sdrh     for(i=0; i<pTab->nCol; i++){
116cce7d176Sdrh       if( pField==0 ){
117cce7d176Sdrh         j = i;
118cce7d176Sdrh       }else{
119cce7d176Sdrh         for(j=0; j<pField->nId; j++){
120cce7d176Sdrh           if( pField->a[j].idx==i ) break;
121cce7d176Sdrh         }
122cce7d176Sdrh       }
123cce7d176Sdrh       if( pField && j>=pField->nId ){
124cce7d176Sdrh         sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
125cce7d176Sdrh       }else{
126cce7d176Sdrh         sqliteExprCode(pParse, pList->a[j].pExpr);
127cce7d176Sdrh       }
128cce7d176Sdrh     }
129cce7d176Sdrh     sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0);
130cce7d176Sdrh     sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
131cce7d176Sdrh     sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
132*bed8690fSdrh     for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
133cce7d176Sdrh       if( pIdx->pNext ){
134cce7d176Sdrh         sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
135cce7d176Sdrh       }
136cce7d176Sdrh       for(i=0; i<pIdx->nField; i++){
137cce7d176Sdrh         int idx = pIdx->aiField[i];
138cce7d176Sdrh         if( pField==0 ){
139cce7d176Sdrh           j = idx;
140cce7d176Sdrh         }else{
141cce7d176Sdrh           for(j=0; j<pField->nId; j++){
142cce7d176Sdrh             if( pField->a[j].idx==idx ) break;
143cce7d176Sdrh           }
144cce7d176Sdrh         }
145cce7d176Sdrh         if( pField && j>=pField->nId ){
146cce7d176Sdrh           sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
147cce7d176Sdrh         }else{
148cce7d176Sdrh           sqliteExprCode(pParse, pList->a[j].pExpr);
149cce7d176Sdrh         }
150cce7d176Sdrh       }
151cce7d176Sdrh       sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nField, 0, 0, 0);
152*bed8690fSdrh       sqliteVdbeAddOp(v, OP_PutIdx, idx, 0, 0, 0);
153*bed8690fSdrh       sqliteVdbeAddOp(v, OP_Close, idx, 0, 0, 0);
154cce7d176Sdrh     }
155cce7d176Sdrh   }
156cce7d176Sdrh 
157cce7d176Sdrh insert_cleanup:
158cce7d176Sdrh   sqliteExprListDelete(pList);
159cce7d176Sdrh   sqliteIdListDelete(pField);
160cce7d176Sdrh }
161