blob: 204c6facd3cad64139427d16b16ef56b3694ffec [file] [log] [blame]
drhcce7d172000-05-31 15:34:51 +00001/*
2** Copyright (c) 1999, 2000 D. Richard Hipp
3**
4** This program is free software; you can redistribute it and/or
5** modify it under the terms of the GNU General Public
6** License as published by the Free Software Foundation; either
7** version 2 of the License, or (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12** General Public License for more details.
13**
14** You should have received a copy of the GNU General Public
15** License along with this library; if not, write to the
16** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17** Boston, MA 02111-1307, USA.
18**
19** Author contact information:
20** drh@hwaci.com
21** http://www.hwaci.com/drh/
22**
23*************************************************************************
24** This file contains C code routines that are called by the parser
25** to handle INSERT statements.
26**
drhcc85b412000-06-07 15:11:27 +000027** $Id: insert.c,v 1.8 2000/06/07 15:11:27 drh Exp $
drhcce7d172000-05-31 15:34:51 +000028*/
29#include "sqliteInt.h"
30
31/*
32** This routine is call to handle SQL of the following form:
33**
34** insert into TABLE (IDLIST) values(EXPRLIST)
35**
36** The parameters are the table name and the expression list.
37*/
38void sqliteInsert(
39 Parse *pParse, /* Parser context */
40 Token *pTableName, /* Name of table into which we are inserting */
41 ExprList *pList, /* List of values to be inserted */
drh5974a302000-06-07 14:42:26 +000042 Select *pSelect, /* A SELECT statement to use as the data source */
drhcce7d172000-05-31 15:34:51 +000043 IdList *pField /* Field name corresponding to pList. Might be NULL */
44){
drh5974a302000-06-07 14:42:26 +000045 Table *pTab; /* The table to insert into */
46 char *zTab; /* Name of the table into which we are inserting */
47 int i, j, idx; /* Loop counters */
48 Vdbe *v; /* Generate code into this virtual machine */
49 Index *pIdx; /* For looping over indices of the table */
50 int srcTab; /* Date comes from this temporary cursor if >=0 */
51 int nField; /* Number of columns in the data */
52 int base; /* First available cursor */
53 int iCont, iBreak; /* Beginning and end of the loop over srcTab */
drhcce7d172000-05-31 15:34:51 +000054
55 zTab = sqliteTableNameFromToken(pTableName);
56 pTab = sqliteFindTable(pParse->db, zTab);
57 sqliteFree(zTab);
58 if( pTab==0 ){
59 sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0,
60 pTableName->z, pTableName->n, 0);
61 pParse->nErr++;
62 goto insert_cleanup;
63 }
64 if( pTab->readOnly ){
65 sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
66 " may not be modified", 0);
67 pParse->nErr++;
68 goto insert_cleanup;
69 }
drh5974a302000-06-07 14:42:26 +000070 v = pParse->pVdbe;
71 if( v==0 ){
72 v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
73 }
74 if( v==0 ) goto insert_cleanup;
75 if( pSelect ){
76 int rc;
77 srcTab = pParse->nTab++;
78 sqliteVdbeAddOp(v, OP_Open, srcTab, 1, 0, 0);
79 rc = sqliteSelect(pParse, pSelect, SRT_Table, srcTab);
80 if( rc ) goto insert_cleanup;
81 assert( pSelect->pEList );
82 nField = pSelect->pEList->nExpr;
83 }else{
84 srcTab = -1;
85 assert( pList );
86 nField = pList->nExpr;
87 }
88 if( pField==0 && nField!=pTab->nCol ){
drhcce7d172000-05-31 15:34:51 +000089 char zNum1[30];
90 char zNum2[30];
drh5974a302000-06-07 14:42:26 +000091 sprintf(zNum1,"%d", nField);
drhcce7d172000-05-31 15:34:51 +000092 sprintf(zNum2,"%d", pTab->nCol);
93 sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
94 " has ", zNum2, " columns but ",
95 zNum1, " values were supplied", 0);
96 pParse->nErr++;
97 goto insert_cleanup;
98 }
drh5974a302000-06-07 14:42:26 +000099 if( pField!=0 && nField!=pField->nId ){
drhcce7d172000-05-31 15:34:51 +0000100 char zNum1[30];
101 char zNum2[30];
drh5974a302000-06-07 14:42:26 +0000102 sprintf(zNum1,"%d", nField);
drhcce7d172000-05-31 15:34:51 +0000103 sprintf(zNum2,"%d", pField->nId);
104 sqliteSetString(&pParse->zErrMsg, zNum1, " values for ",
105 zNum2, " columns", 0);
106 pParse->nErr++;
107 goto insert_cleanup;
108 }
109 if( pField ){
110 for(i=0; i<pField->nId; i++){
111 pField->a[i].idx = -1;
112 }
113 for(i=0; i<pField->nId; i++){
114 for(j=0; j<pTab->nCol; j++){
drh7020f652000-06-03 18:06:52 +0000115 if( sqliteStrICmp(pField->a[i].zName, pTab->aCol[j].zName)==0 ){
drhcce7d172000-05-31 15:34:51 +0000116 pField->a[i].idx = j;
117 break;
118 }
119 }
120 if( j>=pTab->nCol ){
121 sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
122 " has no column named ", pField->a[i].zName, 0);
123 pParse->nErr++;
124 goto insert_cleanup;
125 }
126 }
127 }
drh5974a302000-06-07 14:42:26 +0000128 base = pParse->nTab;
129 sqliteVdbeAddOp(v, OP_Open, base, 1, pTab->zName, 0);
130 for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
131 sqliteVdbeAddOp(v, OP_Open, idx+base, 1, pIdx->zName, 0);
drh19a775c2000-06-05 18:54:46 +0000132 }
drh5974a302000-06-07 14:42:26 +0000133 if( srcTab>=0 ){
134 sqliteVdbeAddOp(v, OP_Rewind, srcTab, 0, 0, 0);
135 iBreak = sqliteVdbeMakeLabel(v);
136 iCont = sqliteVdbeAddOp(v, OP_Next, srcTab, iBreak, 0, 0);
137 }
138 sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0);
139 if( pTab->pIndex ){
140 sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
141 }
142 for(i=0; i<pTab->nCol; i++){
143 if( pField==0 ){
144 j = i;
145 }else{
146 for(j=0; j<pField->nId; j++){
147 if( pField->a[j].idx==i ) break;
148 }
drhbed86902000-06-02 13:27:59 +0000149 }
drh5974a302000-06-07 14:42:26 +0000150 if( pField && j>=pField->nId ){
151 char *zDflt = pTab->aCol[i].zDflt;
152 if( zDflt==0 ){
153 sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
154 }else{
155 sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0);
156 }
157 }else if( srcTab>=0 ){
158 sqliteVdbeAddOp(v, OP_Field, srcTab, i, 0, 0);
159 }else{
160 sqliteExprCode(pParse, pList->a[j].pExpr);
161 }
162 }
163 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0);
164 sqliteVdbeAddOp(v, OP_Put, base, 0, 0, 0);
165 /* sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0); */
166 for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
167 if( pIdx->pNext ){
drhcce7d172000-05-31 15:34:51 +0000168 sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
169 }
drh5974a302000-06-07 14:42:26 +0000170 for(i=0; i<pIdx->nField; i++){
171 int idx = pIdx->aiField[i];
drhcce7d172000-05-31 15:34:51 +0000172 if( pField==0 ){
drh5974a302000-06-07 14:42:26 +0000173 j = idx;
drhcce7d172000-05-31 15:34:51 +0000174 }else{
175 for(j=0; j<pField->nId; j++){
drh5974a302000-06-07 14:42:26 +0000176 if( pField->a[j].idx==idx ) break;
drhcce7d172000-05-31 15:34:51 +0000177 }
178 }
179 if( pField && j>=pField->nId ){
drh5974a302000-06-07 14:42:26 +0000180 char *zDflt = pTab->aCol[idx].zDflt;
drhc61053b2000-06-04 12:58:36 +0000181 if( zDflt==0 ){
182 sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
183 }else{
184 sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0);
185 }
drh5974a302000-06-07 14:42:26 +0000186 }else if( srcTab>=0 ){
drhcc85b412000-06-07 15:11:27 +0000187 sqliteVdbeAddOp(v, OP_Field, srcTab, idx, 0, 0);
drhcce7d172000-05-31 15:34:51 +0000188 }else{
189 sqliteExprCode(pParse, pList->a[j].pExpr);
190 }
191 }
drh5974a302000-06-07 14:42:26 +0000192 sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nField, 0, 0, 0);
193 sqliteVdbeAddOp(v, OP_PutIdx, idx+base, 0, 0, 0);
194 /* sqliteVdbeAddOp(v, OP_Close, idx, 0, 0, 0); */
195 }
196 if( srcTab>=0 ){
197 sqliteVdbeAddOp(v, OP_Goto, 0, iCont, 0, 0);
198 sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, iBreak);
drhcce7d172000-05-31 15:34:51 +0000199 }
200
201insert_cleanup:
drh5974a302000-06-07 14:42:26 +0000202 if( pList ) sqliteExprListDelete(pList);
203 if( pSelect ) sqliteSelectDelete(pSelect);
drhcce7d172000-05-31 15:34:51 +0000204 sqliteIdListDelete(pField);
205}