diff options
author | danielk1977 <danielk1977@noemail.net> | 2004-05-28 11:37:27 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2004-05-28 11:37:27 +0000 |
commit | cbb18d2256deeef705100cfd017de0752215634c (patch) | |
tree | ca593011acf212c6191624a375b28146e57d3fae /src | |
parent | d5788201543b12f62308732cb6ff31ab32933e72 (diff) | |
download | sqlite-cbb18d2256deeef705100cfd017de0752215634c.tar.gz sqlite-cbb18d2256deeef705100cfd017de0752215634c.zip |
Allow CREATE TABLE and CREATE INDEX on attached databases. (CVS 1483)
FossilOrigin-Name: 4984a130ccf3b8e486941a5d0d0cc70a691f0dac
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 226 | ||||
-rw-r--r-- | src/parse.y | 17 | ||||
-rw-r--r-- | src/sqliteInt.h | 12 | ||||
-rw-r--r-- | src/trigger.c | 4 | ||||
-rw-r--r-- | src/util.c | 4 | ||||
-rw-r--r-- | src/vdbe.c | 31 | ||||
-rw-r--r-- | src/vdbeaux.c | 27 |
7 files changed, 241 insertions, 80 deletions
diff --git a/src/build.c b/src/build.c index 679d019e9..fb0aec4a5 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.193 2004/05/22 08:09:11 danielk1977 Exp $ +** $Id: build.c,v 1.194 2004/05/28 11:37:27 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -399,18 +399,59 @@ char *sqlite3TableNameFromToken(Token *pName){ } /* -** Generate code to open the appropriate master table. The table -** opened will be SQLITE_MASTER for persistent tables and -** SQLITE_TEMP_MASTER for temporary tables. The table is opened -** on cursor 0. +** Open the sqlite_master table stored in database number iDb for +** writing. The table is opened using cursor 0. */ -void sqlite3OpenMasterTable(Vdbe *v, int isTemp){ - sqlite3VdbeAddOp(v, OP_Integer, isTemp, 0); +void sqlite3OpenMasterTable(Vdbe *v, int iDb){ + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ } /* +** The token *pName contains the name of a database (either "main" or +** "temp" or the name of an attached db). This routine returns the +** index of the named database in db->aDb[], or -1 if the named db +** does not exist. +*/ +int findDb(sqlite3 *db, Token *pName){ + int i; + for(i=0; i<db->nDb; i++){ + if( pName->n==strlen(db->aDb[i].zName) && + 0==sqlite3StrNICmp(db->aDb[i].zName, pName->z, pName->n) ){ + return i; + } + } + return -1; +} + +static int resolveSchemaName( + Parse *pParse, + Token *pName1, + Token *pName2, + Token **pUnqual +){ + int iDb; + sqlite3 *db = pParse->db; + + if( pName2 && pName2->n>0 ){ + assert( !db->init.busy ); + *pUnqual = pName2; + iDb = findDb(db, pName1); + if( iDb<0 ){ + sqlite3ErrorMsg(pParse, "unknown database %T", pName1); + pParse->nErr++; + return -1; + } + }else{ + assert( db->init.iDb==0 || db->init.busy ); + iDb = db->init.iDb; + *pUnqual = pName1; + } + return iDb; +} + +/* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response ** to a CREATE TABLE statement. In particular, this routine is called @@ -430,7 +471,8 @@ void sqlite3OpenMasterTable(Vdbe *v, int isTemp){ void sqlite3StartTable( Parse *pParse, /* Parser context */ Token *pStart, /* The "CREATE" token */ - Token *pName, /* Name of table or view to create */ + Token *pName1, /* First part of the name of the table or view */ + Token *pName2, /* Second part of the name of the table or view */ int isTemp, /* True if this is a TEMP table */ int isView /* True if this is a VIEW */ ){ @@ -439,9 +481,37 @@ void sqlite3StartTable( char *zName; sqlite *db = pParse->db; Vdbe *v; - int iDb; + int iDb; /* Database number to create the table in */ + Token *pName; /* Unqualified name of the table to create */ + + /* The table or view name to create is passed to this routine via tokens + ** pName1 and pName2. If the table name was fully qualified, for example: + ** + ** CREATE TABLE xxx.yyy (...); + ** + ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if + ** the table name is not fully qualified, i.e.: + ** + ** CREATE TABLE yyy(...); + ** + ** Then pName1 is set to "yyy" and pName2 is "". + ** + ** The call below sets the pName pointer to point at the token (pName1 or + ** pName2) that stores the unqualified table name. The variable iDb is + ** set to the index of the database that the table or view is to be + ** created in. + */ + iDb = resolveSchemaName(pParse, pName1, pName2, &pName); + if( iDb<0 ) return; + if( isTemp && iDb>1 ){ + /* If creating a temp table, the name may not be qualified */ + sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); + pParse->nErr++; + return; + } + if( isTemp ) iDb = 1; - pParse->sFirstToken = *pStart; + pParse->sNameToken = *pName; zName = sqlite3TableNameFromToken(pName); if( zName==0 ) return; if( db->init.iDb==1 ) isTemp = 1; @@ -449,7 +519,7 @@ void sqlite3StartTable( assert( (isTemp & 1)==isTemp ); { int code; - char *zDb = isTemp ? "temp" : "main"; + char *zDb = db->aDb[iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ sqliteFree(zName); return; @@ -473,7 +543,6 @@ void sqlite3StartTable( } } #endif - /* Before trying to create a temporary table, make sure the Btree for ** holding temporary tables is open. @@ -504,7 +573,6 @@ void sqlite3StartTable( ** an existing temporary table, that is not an error. */ pTable = sqlite3FindTable(db, zName, 0); - iDb = isTemp ? 1 : db->init.iDb; if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); sqliteFree(zName); @@ -539,14 +607,18 @@ void sqlite3StartTable( ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ - sqlite3BeginWriteOperation(pParse, 0, isTemp); + sqlite3BeginWriteOperation(pParse, 0, iDb); if( !isTemp ){ + /* Every time a new table is created the file-format + ** and encoding meta-values are set in the database, in + ** case this is the first table created. + */ sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 1); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 4); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); } - sqlite3OpenMasterTable(v, isTemp); + sqlite3OpenMasterTable(v, iDb); sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_String, 0, 0); @@ -721,7 +793,7 @@ void sqlite3AddPrimaryKey(Parse *pParse, IdList *pList, int onError){ pTab->iPKey = iCol; pTab->keyConf = onError; }else{ - sqlite3CreateIndex(pParse, 0, 0, pList, onError, 0, 0); + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); pList = 0; } @@ -850,14 +922,14 @@ char sqlite3AffinityType(const char *zType, int nType){ ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ -void sqlite3ChangeCookie(sqlite *db, Vdbe *v){ +void sqlite3ChangeCookie(sqlite *db, Vdbe *v, int iDb){ if( db->next_cookie==db->aDb[0].schema_cookie ){ unsigned char r; sqlite3Randomness(1, &r); db->next_cookie = db->aDb[0].schema_cookie + r + 1; db->flags |= SQLITE_InternChanges; sqlite3VdbeAddOp(v, OP_Integer, db->next_cookie, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); } } @@ -1015,21 +1087,28 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ sqlite3VdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqlite3VdbeAddOp(v, OP_Dup, 4, 0); - sqlite3VdbeAddOp(v, OP_String, 0, 0); if( pSelect ){ char *z = createTableStmt(p); n = z ? strlen(z) : 0; + sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeChangeP3(v, -1, z, n); sqliteFree(z); }else{ + if( p->pSelect ){ + sqlite3VdbeOp3(v, OP_String, 0, 0, "CREATE VIEW ", P3_STATIC); + }else{ + sqlite3VdbeOp3(v, OP_String, 0, 0, "CREATE TABLE ", P3_STATIC); + } assert( pEnd!=0 ); - n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1; - sqlite3VdbeChangeP3(v, -1, pParse->sFirstToken.z, n); + n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1; + sqlite3VdbeAddOp(v, OP_String, 0, 0); + sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n); + sqlite3VdbeAddOp(v, OP_Concat, 2, 0); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( !p->iDb ){ - sqlite3ChangeCookie(db, v); + sqlite3ChangeCookie(db, v, p->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( pSelect ){ @@ -1079,7 +1158,7 @@ void sqlite3CreateView( Token sEnd; DbFixer sFix; - sqlite3StartTable(pParse, pBegin, pName, isTemp, 1); + sqlite3StartTable(pParse, pBegin, pName, 0, isTemp, 1); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(pSelect); @@ -1349,8 +1428,8 @@ void sqlite3DropTable(Parse *pParse, Token *pName, int isView){ sqlite3VdbeChangeP3(v, base+1, pTable->zName, 0); } - if( pTable->iDb==0 ){ - sqlite3ChangeCookie(db, v); + if( pTable->iDb!=1 ){ /* Temp database has no schema cookie */ + sqlite3ChangeCookie(db, v, pTable->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( !isView ){ @@ -1517,14 +1596,15 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ */ void sqlite3CreateIndex( Parse *pParse, /* All information about this parse */ - Token *pName, /* Name of the index. May be NULL */ - SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */ + Token *pName1, /* First part of index name. May be NULL */ + Token *pName2, /* Second part of index name. May be NULL */ + Token *pTblName, /* Name of the table to index. Use pParse->pNewTable if 0 */ IdList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ Token *pEnd /* The ")" that closes the CREATE INDEX statement */ ){ - Table *pTab; /* Table to be indexed */ + Table *pTab = 0; /* Table to be indexed */ Index *pIndex; /* The index to be created */ char *zName = 0; int i, j; @@ -1533,6 +1613,10 @@ void sqlite3CreateIndex( int isTemp; /* True for a temporary index */ sqlite *db = pParse->db; + int iDb; /* Index of the database that is being written */ + Token *pName = 0; /* Unqualified name of the index to create */ + +/* if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index; if( db->init.busy && sqlite3FixInit(&sFix, pParse, db->init.iDb, "index", pName) @@ -1540,27 +1624,59 @@ void sqlite3CreateIndex( ){ goto exit_create_index; } +*/ /* ** Find the table that is to be indexed. Return early if not found. */ - if( pTable!=0 ){ - assert( pName!=0 ); - assert( pTable->nSrc==1 ); - pTab = sqlite3SrcListLookup(pParse, pTable); + if( pTblName!=0 ){ + char *zTblName; + + /* Use the two-part index name to determine the database + ** to search for the table. If no database name is specified, + ** iDb is set to 0. In this case search both the temp and main + ** databases for the named table. + */ + assert( pName1 && pName2 ); + iDb = resolveSchemaName(pParse, pName1, pName2, &pName); + if( iDb<0 ) goto exit_create_index; + + /* Now search for the table in the database iDb. If iDb is + ** zero, then search both the "main" and "temp" databases. + */ + zTblName = sqlite3TableNameFromToken(pTblName); + if( !zTblName ){ + pParse->nErr++; + pParse->rc = SQLITE_NOMEM; + goto exit_create_index; + } + assert( pName1!=0 ); + if( iDb==0 ){ + pTab = sqlite3FindTable(db, zTblName, "temp"); + } + if( !pTab ){ + pTab = sqlite3LocateTable(pParse, zTblName, db->aDb[iDb].zName); + } + sqliteFree( zTblName ); + if( !pTab ) goto exit_create_index; + iDb = pTab->iDb; }else{ assert( pName==0 ); pTab = pParse->pNewTable; + iDb = pTab->iDb; } + if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } +/* if( pTab->iDb>=2 && db->init.busy==0 ){ sqlite3ErrorMsg(pParse, "table %s may not have indices added", pTab->zName); goto exit_create_index; } +*/ if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; @@ -1611,8 +1727,6 @@ void sqlite3CreateIndex( #ifndef SQLITE_OMIT_AUTHORIZATION { const char *zDb = db->aDb[pTab->iDb].zName; - - assert( pTab->iDb==db->init.iDb || isTemp ); if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto exit_create_index; } @@ -1648,7 +1762,7 @@ void sqlite3CreateIndex( pIndex->nColumn = pList->nId; pIndex->onError = onError; pIndex->autoIndex = pName==0; - pIndex->iDb = isTemp ? 1 : db->init.iDb; + pIndex->iDb = iDb; /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error @@ -1706,7 +1820,7 @@ void sqlite3CreateIndex( ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the table number from the db->init.newTnum field. */ - if( db->init.busy && pTable!=0 ){ + if( db->init.busy && pTblName!=0 ){ pIndex->tnum = db->init.newTnum; } @@ -1720,7 +1834,7 @@ void sqlite3CreateIndex( ** the latter case the index already exists on disk, which is why ** we don't want to recreate it. ** - ** If pTable==0 it means this index is generated as a primary key + ** If pTblName==0 it means this index is generated as a primary key ** or UNIQUE constraint of a CREATE TABLE statement. Since the table ** has just been created, it contains no data and the index initialization ** step can be skipped. @@ -1730,36 +1844,38 @@ void sqlite3CreateIndex( Vdbe *v; int lbl1, lbl2; int i; - int addr; v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; - if( pTable!=0 ){ - sqlite3BeginWriteOperation(pParse, 0, isTemp); - sqlite3OpenMasterTable(v, isTemp); + if( pTblName!=0 ){ + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3OpenMasterTable(v, iDb); } sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC); sqlite3VdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, pTab->zName, 0); - sqlite3VdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER); + sqlite3VdbeOp3(v, OP_CreateIndex, 0, iDb,(char*)&pIndex->tnum,P3_POINTER); pIndex->tnum = 0; - if( pTable ){ + if( pTblName ){ sqlite3VdbeCode(v, OP_Dup, 0, 0, - OP_Integer, isTemp, 0, + OP_Integer, iDb, 0, 0); sqlite3VdbeOp3(v, OP_OpenWrite, 1, 0, (char*)&pIndex->keyInfo, P3_KEYINFO); } - addr = sqlite3VdbeAddOp(v, OP_String, 0, 0); + sqlite3VdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ - n = Addr(pEnd->z) - Addr(pStart->z) + 1; - sqlite3VdbeChangeP3(v, addr, pStart->z, n); + sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", n); + sqlite3VdbeAddOp(v, OP_String, 0, 0); + n = Addr(pEnd->z) - Addr(pName->z) + 1; + sqlite3VdbeChangeP3(v, -1, pName->z, n); + sqlite3VdbeAddOp(v, OP_Concat, 2, 0); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); - if( pTable ){ + if( pTblName ){ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenRead, 2, pTab->tnum); /* VdbeComment((v, "%s", pTab->zName)); */ @@ -1784,9 +1900,9 @@ void sqlite3CreateIndex( sqlite3VdbeAddOp(v, OP_Close, 2, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); } - if( pTable!=0 ){ + if( pTblName!=0 ){ if( !isTemp ){ - sqlite3ChangeCookie(db, v); + sqlite3ChangeCookie(db, v, iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); @@ -1796,7 +1912,7 @@ void sqlite3CreateIndex( /* Clean up before exiting */ exit_create_index: sqlite3IdListDelete(pList); - sqlite3SrcListDelete(pTable); + /* sqlite3SrcListDelete(pTable); */ sqliteFree(zName); return; } @@ -1863,8 +1979,8 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ sqlite3OpenMasterTable(v, pIndex->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0); - if( pIndex->iDb==0 ){ - sqlite3ChangeCookie(db, v); + if( pIndex->iDb!=1 ){ + sqlite3ChangeCookie(db, v, pIndex->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); diff --git a/src/parse.y b/src/parse.y index 4a0657bbf..fc14b5d60 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.119 2004/05/27 17:22:55 drh Exp $ +** @(#) $Id: parse.y,v 1.120 2004/05/28 11:37:28 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} @@ -87,8 +87,8 @@ cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} ///////////////////// The CREATE TABLE statement //////////////////////////// // cmd ::= create_table create_table_args. -create_table ::= CREATE(X) temp(T) TABLE nm(Y). { - sqlite3StartTable(pParse,&X,&Y,T,0); +create_table ::= CREATE(X) temp(T) TABLE nm(Y) dbnm(Z). { + sqlite3StartTable(pParse,&X,&Y,&Z,T,0); } %type temp {int} temp(A) ::= TEMP. {A = 1;} @@ -188,7 +188,7 @@ carg ::= DEFAULT NULL. ccons ::= NULL onconf. ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} ccons ::= PRIMARY KEY sortorder onconf(R). {sqlite3AddPrimaryKey(pParse,0,R);} -ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,R,0,0);} +ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);} ccons ::= CHECK LP expr RP onconf. ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} @@ -233,7 +233,7 @@ tcons ::= CONSTRAINT nm. tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). {sqlite3AddPrimaryKey(pParse,X,R);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). - {sqlite3CreateIndex(pParse,0,0,X,R,0,0);} + {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);} tcons ::= CHECK expr onconf. tcons ::= FOREIGN KEY LP idxlist(FA) RP REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { @@ -727,12 +727,11 @@ expritem(A) ::= . {A = 0;} ///////////////////////////// The CREATE INDEX command /////////////////////// // -cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) - ON nm(Y) dbnm(D) LP idxlist(Z) RP(E) onconf(R). { - SrcList *pSrc = sqlite3SrcListAppend(0, &Y, &D); +cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D) + ON nm(Y) LP idxlist(Z) RP(E) onconf(R). { if( U!=OE_None ) U = R; if( U==OE_Default) U = OE_Abort; - sqlite3CreateIndex(pParse, &X, pSrc, Z, U, &S, &E); + sqlite3CreateIndex(pParse, &X, &D, &Y, Z, U, &S, &E); } %type uniqueflag {int} diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 454d4d4f4..7f77a47bb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.256 2004/05/27 17:22:56 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.257 2004/05/28 11:37:28 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" @@ -969,7 +969,7 @@ struct Parse { int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ - Token sFirstToken; /* The first token parsed */ + Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ @@ -1199,7 +1199,7 @@ void sqlite3RollbackInternalChanges(sqlite*); void sqlite3CommitInternalChanges(sqlite*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); void sqlite3OpenMasterTable(Vdbe *v, int); -void sqlite3StartTable(Parse*,Token*,Token*,int,int); +void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, IdList*, int); @@ -1221,7 +1221,7 @@ void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); -void sqlite3CreateIndex(Parse*,Token*,SrcList*,IdList*,int,Token*,Token*); +void sqlite3CreateIndex(Parse*,Token*,Token*,Token*,IdList*,int,Token*,Token*); void sqlite3DropIndex(Parse*, SrcList*); void sqlite3AddKeyType(Vdbe*, ExprList*); void sqlite3AddIdxKeyType(Vdbe*, Index*); @@ -1284,7 +1284,7 @@ void sqlite3RegisterDateTimeFunctions(sqlite*); int sqlite3SafetyOn(sqlite*); int sqlite3SafetyOff(sqlite*); int sqlite3SafetyCheck(sqlite*); -void sqlite3ChangeCookie(sqlite*, Vdbe*); +void sqlite3ChangeCookie(sqlite*, Vdbe*, int); void sqlite3BeginTrigger(Parse*, Token*,int,int,IdList*,SrcList*,int,Expr*,int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*); @@ -1350,4 +1350,4 @@ int sqlite3atoi64(const char*, i64*); void sqlite3Error(sqlite *, int, const char*,...); int sqlite3utfTranslate(const void *, int , u8 , void **, int *, u8); u8 sqlite3UtfReadBom(const void *zData, int nData); -char *sqlite3HexToBlob(const char *z); +void *sqlite3HexToBlob(const char *z); diff --git a/src/trigger.c b/src/trigger.c index 758513e4c..e224db6f5 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -205,7 +205,7 @@ void sqlite3FinishTrigger( sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); sqlite3VdbeChangeP3(v, addr+5, pAll->z, pAll->n); if( nt->iDb==0 ){ - sqlite3ChangeCookie(db, v); + sqlite3ChangeCookie(db, v, 0); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); @@ -467,7 +467,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); if( pTrigger->iDb==0 ){ - sqlite3ChangeCookie(db, v); + sqlite3ChangeCookie(db, v, 0); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); diff --git a/src/util.c b/src/util.c index 27c94bc02..92dff9131 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.92 2004/05/27 13:35:20 danielk1977 Exp $ +** $Id: util.c,v 1.93 2004/05/28 11:37:28 danielk1977 Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -1299,7 +1299,7 @@ int sqlite3VarintLen(u64 v){ return i; } -char * sqlite3HexToBlob(const char *z){ +void *sqlite3HexToBlob(const char *z){ char *zBlob; int i; int n = strlen(z); diff --git a/src/vdbe.c b/src/vdbe.c index 4d7ea7cfe..e695961b9 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.343 2004/05/28 08:21:09 drh Exp $ +** $Id: vdbe.c,v 1.344 2004/05/28 11:37:28 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -693,20 +693,39 @@ case OP_Real: { Realify(pTos, 0); break; } + +#if 0 +/* Opcode: String8 * * P3 +** +** This opcode does not exist at vdbe execution time. +*/ +case OP_String8: { + break; +} +#endif /* Opcode: String * * P3 ** ** The string value P3 is pushed onto the stack. If P3==0 then a -** NULL is pushed onto the stack. +** NULL is pushed onto the stack. P3 is assumed to be a nul terminated +** string encoded with the database native encoding. */ case OP_String: { pTos++; if( pOp->p3 ){ pTos->flags = MEM_Str|MEM_Static|MEM_Term; - pTos->enc = TEXT_Utf8; pTos->z = pOp->p3; pTos->n = strlen(pTos->z); + pTos->enc = TEXT_Utf8; sqlite3VdbeChangeEncoding(pTos, db->enc); +/* + if( db->enc==TEXT_Utf8 ){ + pTos->n = strlen(pTos->z); + }else{ + pTos->n = sqlite3utf16ByteLen(pTos->z, -1); + } + pTos->enc = db->enc; +*/ }else{ pTos->flags = MEM_Null; } @@ -726,7 +745,11 @@ case OP_HexBlob: { /* Opcode: Blob P1 * P3 ** ** P3 points to a blob of data P1 bytes long. Push this -** value onto the stack. +** value onto the stack. This instruction is not coded directly +** by the compiler. Instead, the compiler layer specifies +** an OP_HexBlob opcode, with the hex string representation of +** the blob as P3. This opcode is transformed to an OP_Blob +** before execution (within the sqlite3_prepare() function). */ case OP_Blob: { pTos++; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e643284b0..93a30fd30 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -610,7 +610,8 @@ int sqlite3VdbeList( ** If pOp is an OP_HexBlob opcode, then transform it to an OP_Blob ** opcode. */ -static int translateOp(Op *pOp){ +static int translateOp(Op *pOp, u8 enc){ + if( pOp->opcode==OP_HexBlob ){ pOp->p1 = strlen(pOp->p3)/2; if( pOp->p1 ){ @@ -627,6 +628,28 @@ static int translateOp(Op *pOp){ } pOp->opcode = OP_Blob; } + + else if( pOp->opcode==OP_String8 ){ + if( pOp->p3 ){ + void *z = 0; + switch( enc ){ + case TEXT_Utf16be: + z = sqlite3utf8to16be(pOp->p3, -1); + if( !z ) return SQLITE_NOMEM; + break; + case TEXT_Utf16le: + z = sqlite3utf8to16be(pOp->p3, -1); + if( !z ) return SQLITE_NOMEM; + break; + } + if( z ){ + if( pOp->p3type==P3_DYNAMIC ) sqliteFree( pOp->p3 ); + + } + } + pOp->opcode = OP_String; + } + return SQLITE_OK; } @@ -704,7 +727,7 @@ void sqlite3VdbeMakeReady( if( !isExplain ){ int i; for(i=0; i<p->nOp; i++){ - translateOp(&p->aOp[i]); + translateOp(&p->aOp[i], p->db->enc); } } } |