mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Change the SQLITE_MASTER format to version 2 in preparation for adding views. (CVS 386)
FossilOrigin-Name: b2a9807fed544e83002366149b9a363759338c5d
This commit is contained in:
28
manifest
28
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Do\snot\sallow\sdot-commands\sto\soccur\sin\sthe\smiddle\sof\sa\sreal\sSQL\scommand.\s(CVS\s385)
|
C Change\sthe\sSQLITE_MASTER\sformat\sto\sversion\s2\sin\spreparation\sfor\sadding\sviews.\s(CVS\s386)
|
||||||
D 2002-02-21T02:25:03
|
D 2002-02-21T12:01:27
|
||||||
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
|
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
|
||||||
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
|
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
|
||||||
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
||||||
@@ -21,13 +21,13 @@ F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
|
|||||||
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
|
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
|
||||||
F src/btree.c 495275fe14f3b718cf2f691dce979d4c0e1f8e5d
|
F src/btree.c 495275fe14f3b718cf2f691dce979d4c0e1f8e5d
|
||||||
F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
|
F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
|
||||||
F src/build.c 088acf87a92b00edda1206ccafac3518660b1b3b
|
F src/build.c 4e10d8e61971fe900317d00a98f49dd7ceb27c20
|
||||||
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
|
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
|
||||||
F src/expr.c 7aff65ea0732b07d36925087ad611019103ad69a
|
F src/expr.c 7aff65ea0732b07d36925087ad611019103ad69a
|
||||||
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
|
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
|
||||||
F src/hash.h d1ce47900c7325af5e41c4feb4855c4bf2b841e7
|
F src/hash.h d1ce47900c7325af5e41c4feb4855c4bf2b841e7
|
||||||
F src/insert.c eae5aa2e9ac68c4d465e71b2ad34bcbb882979cf
|
F src/insert.c eae5aa2e9ac68c4d465e71b2ad34bcbb882979cf
|
||||||
F src/main.c fada622b468c54fb211372f38a27ee636915e2ee
|
F src/main.c abc0732d4caa676ff8337f278b01f1f1b57538f5
|
||||||
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
|
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
|
||||||
F src/os.c f6bc9b7ab530346bb7fef2ed39f2f1f214bc14ea
|
F src/os.c f6bc9b7ab530346bb7fef2ed39f2f1f214bc14ea
|
||||||
F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6
|
F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6
|
||||||
@@ -36,22 +36,22 @@ F src/pager.h b28f004e2f5541dc60cc32db01bf80cf4d056283
|
|||||||
F src/parse.y b82278917959eefd05bd08c90e07a4fa5917ea51
|
F src/parse.y b82278917959eefd05bd08c90e07a4fa5917ea51
|
||||||
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
|
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
|
||||||
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
|
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
|
||||||
F src/select.c 282f37b2fdb9367f0230811e1cf7bba48665fb72
|
F src/select.c f0cbfd2d9059e0f33837797ee326fbe964a35f09
|
||||||
F src/shell.c cbf48bf0ca35c4e0d8a7d2a86f7724f52c525cd7
|
F src/shell.c cbf48bf0ca35c4e0d8a7d2a86f7724f52c525cd7
|
||||||
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
||||||
F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
|
F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
|
||||||
F src/sqliteInt.h e19efd5b1c6accfb3418cbb5c0e8c143fc1d18d7
|
F src/sqliteInt.h 338cd586b9322105080a2a31122446e504ac1fc4
|
||||||
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
|
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
|
||||||
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
|
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
|
||||||
F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
|
F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
|
||||||
F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
|
F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
|
||||||
F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
|
F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
|
||||||
F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
|
F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
|
||||||
F src/tokenize.c 9e98f94469694a763992860596137e78dbae0cc0
|
F src/tokenize.c 777b734f9d06f5a9055b6808e5baec18936a4fd9
|
||||||
F src/update.c 95459f94a061860bf8e5716b3426a5ba85c79103
|
F src/update.c 95459f94a061860bf8e5716b3426a5ba85c79103
|
||||||
F src/util.c f31f3d6198a0d1296a16f5a6ceec423a932cbbf6
|
F src/util.c f31f3d6198a0d1296a16f5a6ceec423a932cbbf6
|
||||||
F src/vdbe.c 18b6e9ed3bcdd76ae74d60a977a6d8a3a1b0f797
|
F src/vdbe.c 44832d804e109248e9e2abd40daee5f8ac735450
|
||||||
F src/vdbe.h b4d35e159fbb80a74728b4a96e5b789fffce6f57
|
F src/vdbe.h 002bb8cf884034bea25a9fe901a9c5e9d29bc045
|
||||||
F src/where.c f79bc3179379b46b131a67ab10713779368dceee
|
F src/where.c f79bc3179379b46b131a67ab10713779368dceee
|
||||||
F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
|
F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
|
||||||
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
|
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
|
||||||
@@ -89,7 +89,7 @@ F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
|
|||||||
F test/select6.test d9fb417d6cab75a072b547ba6303120f327fd6fd
|
F test/select6.test d9fb417d6cab75a072b547ba6303120f327fd6fd
|
||||||
F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b
|
F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b
|
||||||
F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78
|
F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78
|
||||||
F test/table.test b8be4d3d3ff6b4858516fa274d38075ba06b5004
|
F test/table.test 17b0b6eafa3faaee5545b7a94e6c1ff73f0880f3
|
||||||
F test/tableapi.test 51d0c209aa6b1158cb952ec917c656d4ce66e9e4
|
F test/tableapi.test 51d0c209aa6b1158cb952ec917c656d4ce66e9e4
|
||||||
F test/tclsqlite.test ca8dd89b02ab68bd4540163c24551756a69f6783
|
F test/tclsqlite.test ca8dd89b02ab68bd4540163c24551756a69f6783
|
||||||
F test/temptable.test 0e9934283259a5e637eec756a7eefd6964c0f79b
|
F test/temptable.test 0e9934283259a5e637eec756a7eefd6964c0f79b
|
||||||
@@ -110,7 +110,7 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
|
|||||||
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
|
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
|
||||||
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
|
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
|
||||||
F www/c_interface.tcl 63efc40f09e2f0d8fea43d174103248b160fdf0e
|
F www/c_interface.tcl 63efc40f09e2f0d8fea43d174103248b160fdf0e
|
||||||
F www/changes.tcl e9ac5ffc030ad355fb5973bc2c68e622c3bc9ae2
|
F www/changes.tcl 4aee975940a59d43736cdd4cd352c51e1e6426ba
|
||||||
F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
|
F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
|
||||||
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
|
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
|
||||||
F www/download.tcl a6d75b8b117cd33dcb090bef7e80d7556d28ebe0
|
F www/download.tcl a6d75b8b117cd33dcb090bef7e80d7556d28ebe0
|
||||||
@@ -125,7 +125,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
|
|||||||
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
|
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
|
||||||
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
|
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
|
||||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||||
P 953928537c350e6c9df157553114c6d9d44712d5
|
P ffb00bf36a9a5851ea4a69f9c7dd7ce412553e3b
|
||||||
R 9ed6435fa0cf461ec879e5b28166d8d6
|
R 827e990a5d306ede002baf12f96964e4
|
||||||
U drh
|
U drh
|
||||||
Z a1b5da6dd8cc3bb5ba9dca0ec016a36c
|
Z 93dfb9234ed5554b3f3a0a3a7b0ddf3a
|
||||||
|
@@ -1 +1 @@
|
|||||||
ffb00bf36a9a5851ea4a69f9c7dd7ce412553e3b
|
b2a9807fed544e83002366149b9a363759338c5d
|
39
src/build.c
39
src/build.c
@@ -25,7 +25,7 @@
|
|||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
** PRAGMA
|
** PRAGMA
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.77 2002/02/19 13:39:22 drh Exp $
|
** $Id: build.c,v 1.78 2002/02/21 12:01:27 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -473,12 +473,25 @@ void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName, int isTemp){
|
|||||||
pTable->isTemp = isTemp;
|
pTable->isTemp = isTemp;
|
||||||
if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
|
if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
|
||||||
pParse->pNewTable = pTable;
|
pParse->pNewTable = pTable;
|
||||||
|
|
||||||
|
/* Begin generating the code that will insert the table record into
|
||||||
|
** the SQLITE_MASTER table. Note in particular that we must go ahead
|
||||||
|
** and allocate the record number for the table entry now. Before any
|
||||||
|
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
|
||||||
|
** indices to be created and the table record must come before the
|
||||||
|
** indices. Hence, the record number for the table must be allocated
|
||||||
|
** now.
|
||||||
|
*/
|
||||||
if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
|
if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
|
||||||
sqliteBeginWriteOperation(pParse);
|
sqliteBeginWriteOperation(pParse);
|
||||||
if( !isTemp ){
|
if( !isTemp ){
|
||||||
sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
|
sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
|
||||||
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
|
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
|
||||||
sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
|
sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
|
||||||
|
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||||
|
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -657,10 +670,11 @@ static void changeCookie(sqlite *db){
|
|||||||
*/
|
*/
|
||||||
static int identLength(const char *z){
|
static int identLength(const char *z){
|
||||||
int n;
|
int n;
|
||||||
for(n=2; *z; n++, z++){
|
int needQuote = 0;
|
||||||
if( *z=='\'' ){ n++; }
|
for(n=0; *z; n++, z++){
|
||||||
|
if( *z=='\'' ){ n++; needQuote=1; }
|
||||||
}
|
}
|
||||||
return n;
|
return n + needQuote*2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -668,14 +682,19 @@ static int identLength(const char *z){
|
|||||||
** quote characters as needed.
|
** quote characters as needed.
|
||||||
*/
|
*/
|
||||||
static void identPut(char *z, int *pIdx, char *zIdent){
|
static void identPut(char *z, int *pIdx, char *zIdent){
|
||||||
int i, j;
|
int i, j, needQuote;
|
||||||
i = *pIdx;
|
i = *pIdx;
|
||||||
z[i++] = '\'';
|
for(j=0; zIdent[j]; j++){
|
||||||
|
if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
|
||||||
|
}
|
||||||
|
needQuote = zIdent[j]!=0 || isdigit(zIdent[0])
|
||||||
|
|| sqliteKeywordCode(zIdent, j)!=TK_ID;
|
||||||
|
if( needQuote ) z[i++] = '\'';
|
||||||
for(j=0; zIdent[j]; j++){
|
for(j=0; zIdent[j]; j++){
|
||||||
z[i++] = zIdent[j];
|
z[i++] = zIdent[j];
|
||||||
if( zIdent[j]=='\'' ) z[i++] = '\'';
|
if( zIdent[j]=='\'' ) z[i++] = '\'';
|
||||||
}
|
}
|
||||||
z[i++] = '\'';
|
if( needQuote ) z[i++] = '\'';
|
||||||
z[i] = 0;
|
z[i] = 0;
|
||||||
*pIdx = i;
|
*pIdx = i;
|
||||||
}
|
}
|
||||||
@@ -769,6 +788,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
|
|||||||
*/
|
*/
|
||||||
if( pSelect ){
|
if( pSelect ){
|
||||||
Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
|
Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
|
||||||
|
if( pSelTab==0 ) return;
|
||||||
assert( p->aCol==0 );
|
assert( p->aCol==0 );
|
||||||
p->nCol = pSelTab->nCol;
|
p->nCol = pSelTab->nCol;
|
||||||
p->aCol = pSelTab->aCol;
|
p->aCol = pSelTab->aCol;
|
||||||
@@ -788,7 +808,8 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If not initializing, then create a record for the new table
|
/* If not initializing, then create a record for the new table
|
||||||
** in the SQLITE_MASTER table of the database.
|
** in the SQLITE_MASTER table of the database. The record number
|
||||||
|
** for the new table entry should already be on the stack.
|
||||||
**
|
**
|
||||||
** If this is a TEMPORARY table, then just create the table. Do not
|
** If this is a TEMPORARY table, then just create the table. Do not
|
||||||
** make an entry in SQLITE_MASTER.
|
** make an entry in SQLITE_MASTER.
|
||||||
@@ -803,7 +824,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
|
|||||||
sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
|
sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
|
||||||
p->tnum = 0;
|
p->tnum = 0;
|
||||||
if( !p->isTemp ){
|
if( !p->isTemp ){
|
||||||
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
|
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
|
||||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||||
sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
|
sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
|
||||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||||
|
76
src/main.c
76
src/main.c
@@ -14,7 +14,7 @@
|
|||||||
** other files are for internal use by SQLite and should not be
|
** other files are for internal use by SQLite and should not be
|
||||||
** accessed by users of the library.
|
** accessed by users of the library.
|
||||||
**
|
**
|
||||||
** $Id: main.c,v 1.60 2002/02/19 22:42:05 drh Exp $
|
** $Id: main.c,v 1.61 2002/02/21 12:01:27 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -51,13 +51,14 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
|
|||||||
db->next_cookie = db->schema_cookie;
|
db->next_cookie = db->schema_cookie;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'v':
|
||||||
case 'i':
|
case 'i':
|
||||||
case 't': { /* CREATE TABLE and CREATE INDEX statements */
|
case 't': { /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
|
||||||
if( argv[3] && argv[3][0] ){
|
if( argv[3] && argv[3][0] ){
|
||||||
/* Call the parser to process a CREATE TABLE or CREATE INDEX statement.
|
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
|
||||||
** But because sParse.initFlag is set to 1, no VDBE code is generated
|
** But because sParse.initFlag is set to 1, no VDBE code is generated
|
||||||
** or executed. All the parser does is build the internal data
|
** or executed. All the parser does is build the internal data
|
||||||
** structures that describe the table or index.
|
** structures that describe the table, index, or view.
|
||||||
*/
|
*/
|
||||||
memset(&sParse, 0, sizeof(sParse));
|
memset(&sParse, 0, sizeof(sParse));
|
||||||
sParse.db = db;
|
sParse.db = db;
|
||||||
@@ -149,10 +150,15 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){
|
|||||||
** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table,
|
** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table,
|
||||||
** then the "sql" column is NULL.
|
** then the "sql" column is NULL.
|
||||||
**
|
**
|
||||||
** If the "type" column has the value "meta", then the "sql" column
|
** In format 1, entries in the sqlite_master table are in a random
|
||||||
** contains extra information about the database, such as the
|
** order. Two passes must be made through the table to initialize
|
||||||
** file format version number. All meta information must be processed
|
** internal data structures. The first pass reads table definitions
|
||||||
** before any tables or indices are constructed.
|
** and the second pass read index definitions. Having two passes
|
||||||
|
** insures that indices appear after their tables.
|
||||||
|
**
|
||||||
|
** In format 2, entries appear in chronological order. Only a single
|
||||||
|
** pass needs to be made through the table since everything will be
|
||||||
|
** in the write order. VIEWs may only occur in format 2.
|
||||||
**
|
**
|
||||||
** The following program invokes its callback on the SQL for each
|
** The following program invokes its callback on the SQL for each
|
||||||
** table then goes back and invokes the callback on the
|
** table then goes back and invokes the callback on the
|
||||||
@@ -161,38 +167,70 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){
|
|||||||
** database scheme.
|
** database scheme.
|
||||||
*/
|
*/
|
||||||
static VdbeOp initProg[] = {
|
static VdbeOp initProg[] = {
|
||||||
|
/* Send the file format to the callback routine
|
||||||
|
*/
|
||||||
{ OP_Open, 0, 2, 0},
|
{ OP_Open, 0, 2, 0},
|
||||||
{ OP_String, 0, 0, "file-format"},
|
{ OP_String, 0, 0, "file-format"},
|
||||||
{ OP_String, 0, 0, 0},
|
{ OP_String, 0, 0, 0},
|
||||||
{ OP_String, 0, 0, 0},
|
{ OP_String, 0, 0, 0},
|
||||||
{ OP_ReadCookie, 0, 1, 0},
|
{ OP_ReadCookie, 0, 1, 0},
|
||||||
{ OP_Callback, 4, 0, 0},
|
{ OP_Callback, 4, 0, 0},
|
||||||
|
|
||||||
|
/* Send the initial schema cookie to the callback
|
||||||
|
*/
|
||||||
{ OP_String, 0, 0, "schema_cookie"},
|
{ OP_String, 0, 0, "schema_cookie"},
|
||||||
{ OP_String, 0, 0, 0},
|
{ OP_String, 0, 0, 0},
|
||||||
{ OP_String, 0, 0, 0},
|
{ OP_String, 0, 0, 0},
|
||||||
{ OP_ReadCookie, 0, 0, 0},
|
{ OP_ReadCookie, 0, 0, 0},
|
||||||
{ OP_Callback, 4, 0, 0},
|
{ OP_Callback, 4, 0, 0},
|
||||||
{ OP_Rewind, 0, 31, 0},
|
|
||||||
{ OP_Column, 0, 0, 0}, /* 12 */
|
/* Check the file format. If the format number is 2 or more,
|
||||||
|
** then do a single pass through the SQLITE_MASTER table. For
|
||||||
|
** a format number of less than 2, jump forward to a different
|
||||||
|
** algorithm that makes two passes through the SQLITE_MASTER table,
|
||||||
|
** once for tables and a second time for indices.
|
||||||
|
*/
|
||||||
|
{ OP_ReadCookie, 0, 1, 0},
|
||||||
|
{ OP_Integer, 2, 0, 0},
|
||||||
|
{ OP_Lt, 0, 23, 0},
|
||||||
|
|
||||||
|
/* This is the code for doing a single scan through the SQLITE_MASTER
|
||||||
|
** table. This code runs for format 2 and greater.
|
||||||
|
*/
|
||||||
|
{ OP_Rewind, 0, 21, 0},
|
||||||
|
{ OP_Column, 0, 0, 0}, /* 15 */
|
||||||
|
{ OP_Column, 0, 1, 0},
|
||||||
|
{ OP_Column, 0, 3, 0},
|
||||||
|
{ OP_Column, 0, 4, 0},
|
||||||
|
{ OP_Callback, 4, 0, 0},
|
||||||
|
{ OP_Next, 0, 15, 0},
|
||||||
|
{ OP_Close, 0, 0, 0}, /* 21 */
|
||||||
|
{ OP_Halt, 0, 0, 0},
|
||||||
|
|
||||||
|
/* This is the code for doing two passes through SQLITE_MASTER. This
|
||||||
|
** code runs for file format 1.
|
||||||
|
*/
|
||||||
|
{ OP_Rewind, 0, 43, 0}, /* 23 */
|
||||||
|
{ OP_Column, 0, 0, 0}, /* 24 */
|
||||||
{ OP_String, 0, 0, "table"},
|
{ OP_String, 0, 0, "table"},
|
||||||
{ OP_Ne, 0, 20, 0},
|
{ OP_Ne, 0, 32, 0},
|
||||||
{ OP_Column, 0, 0, 0},
|
{ OP_Column, 0, 0, 0},
|
||||||
{ OP_Column, 0, 1, 0},
|
{ OP_Column, 0, 1, 0},
|
||||||
{ OP_Column, 0, 3, 0},
|
{ OP_Column, 0, 3, 0},
|
||||||
{ OP_Column, 0, 4, 0},
|
{ OP_Column, 0, 4, 0},
|
||||||
{ OP_Callback, 4, 0, 0},
|
{ OP_Callback, 4, 0, 0},
|
||||||
{ OP_Next, 0, 12, 0}, /* 20 */
|
{ OP_Next, 0, 24, 0}, /* 32 */
|
||||||
{ OP_Rewind, 0, 31, 0}, /* 21 */
|
{ OP_Rewind, 0, 43, 0}, /* 33 */
|
||||||
{ OP_Column, 0, 0, 0}, /* 22 */
|
{ OP_Column, 0, 0, 0}, /* 34 */
|
||||||
{ OP_String, 0, 0, "index"},
|
{ OP_String, 0, 0, "index"},
|
||||||
{ OP_Ne, 0, 30, 0},
|
{ OP_Ne, 0, 42, 0},
|
||||||
{ OP_Column, 0, 0, 0},
|
{ OP_Column, 0, 0, 0},
|
||||||
{ OP_Column, 0, 1, 0},
|
{ OP_Column, 0, 1, 0},
|
||||||
{ OP_Column, 0, 3, 0},
|
{ OP_Column, 0, 3, 0},
|
||||||
{ OP_Column, 0, 4, 0},
|
{ OP_Column, 0, 4, 0},
|
||||||
{ OP_Callback, 4, 0, 0},
|
{ OP_Callback, 4, 0, 0},
|
||||||
{ OP_Next, 0, 22, 0}, /* 30 */
|
{ OP_Next, 0, 34, 0}, /* 42 */
|
||||||
{ OP_Close, 0, 0, 0}, /* 31 */
|
{ OP_Close, 0, 0, 0}, /* 43 */
|
||||||
{ OP_Halt, 0, 0, 0},
|
{ OP_Halt, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,9 +247,9 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){
|
|||||||
db->pBusyArg, db->xBusyCallback);
|
db->pBusyArg, db->xBusyCallback);
|
||||||
sqliteVdbeDelete(vdbe);
|
sqliteVdbeDelete(vdbe);
|
||||||
if( rc==SQLITE_OK && db->nTable==0 ){
|
if( rc==SQLITE_OK && db->nTable==0 ){
|
||||||
db->file_format = FILE_FORMAT;
|
db->file_format = 2;
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK && db->file_format>FILE_FORMAT ){
|
if( rc==SQLITE_OK && db->file_format>2 ){
|
||||||
sqliteSetString(pzErrMsg, "unsupported file format", 0);
|
sqliteSetString(pzErrMsg, "unsupported file format", 0);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
14
src/select.c
14
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.63 2002/02/19 22:42:05 drh Exp $
|
** $Id: select.c,v 1.64 2002/02/21 12:01:27 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -760,7 +760,10 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||||||
pTab = p->pSrc->a[0].pTab;
|
pTab = p->pSrc->a[0].pTab;
|
||||||
|
|
||||||
/* If we get to here, it means the query is of the correct form.
|
/* If we get to here, it means the query is of the correct form.
|
||||||
** Check to make sure we have an index.
|
** Check to make sure we have an index and make pIdx point to the
|
||||||
|
** appropriate index. If the min() or max() is on an INTEGER PRIMARY
|
||||||
|
** key column, no index is necessary so set pIdx to NULL. If no
|
||||||
|
** usable index is found, return 0.
|
||||||
*/
|
*/
|
||||||
if( iCol<0 ){
|
if( iCol<0 ){
|
||||||
pIdx = 0;
|
pIdx = 0;
|
||||||
@@ -772,7 +775,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||||||
if( pIdx==0 ) return 0;
|
if( pIdx==0 ) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Identify column names if we will be using in the callback. This
|
/* Identify column names if we will be using the callback. This
|
||||||
** step is skipped if the output is going to a table or a memory cell.
|
** step is skipped if the output is going to a table or a memory cell.
|
||||||
*/
|
*/
|
||||||
v = sqliteGetVdbe(pParse);
|
v = sqliteGetVdbe(pParse);
|
||||||
@@ -781,7 +784,10 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
|||||||
generateColumnNames(pParse, p->pSrc, p->pEList);
|
generateColumnNames(pParse, p->pSrc, p->pEList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Begin generating code
|
/* Generating code to find the min or the max. Basically all we have
|
||||||
|
** to do is find the first or the last entry in the chosen index. If
|
||||||
|
** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
|
||||||
|
** or last entry in the main table.
|
||||||
*/
|
*/
|
||||||
if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){
|
if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){
|
||||||
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
|
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.88 2002/02/19 22:42:05 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.89 2002/02/21 12:01:27 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqlite.h"
|
#include "sqlite.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
@@ -30,11 +30,6 @@
|
|||||||
#define MAX_PAGES 100
|
#define MAX_PAGES 100
|
||||||
#define TEMP_PAGES 25
|
#define TEMP_PAGES 25
|
||||||
|
|
||||||
/*
|
|
||||||
** File format version number
|
|
||||||
*/
|
|
||||||
#define FILE_FORMAT 1
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Integers of known sizes. These typedefs might change for architectures
|
** Integers of known sizes. These typedefs might change for architectures
|
||||||
** where the sizes very. Preprocessor macros are available so that the
|
** where the sizes very. Preprocessor macros are available so that the
|
||||||
@@ -555,6 +550,7 @@ void sqliteRealToSortable(double r, char *);
|
|||||||
void sqliteSetString(char **, const char *, ...);
|
void sqliteSetString(char **, const char *, ...);
|
||||||
void sqliteSetNString(char **, ...);
|
void sqliteSetNString(char **, ...);
|
||||||
void sqliteDequote(char*);
|
void sqliteDequote(char*);
|
||||||
|
int sqliteKeywordCode(const char*, int);
|
||||||
int sqliteRunParser(Parse*, const char*, char **);
|
int sqliteRunParser(Parse*, const char*, char **);
|
||||||
void sqliteExec(Parse*);
|
void sqliteExec(Parse*);
|
||||||
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
|
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
** individual tokens and sends those tokens one-by-one over to the
|
** individual tokens and sends those tokens one-by-one over to the
|
||||||
** parser for analysis.
|
** parser for analysis.
|
||||||
**
|
**
|
||||||
** $Id: tokenize.c,v 1.36 2002/02/17 00:30:36 drh Exp $
|
** $Id: tokenize.c,v 1.37 2002/02/21 12:01:27 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -116,7 +116,7 @@ static Keyword *apHashTable[KEY_HASH_SIZE];
|
|||||||
** keyword. If it is a keyword, the token code of that keyword is
|
** keyword. If it is a keyword, the token code of that keyword is
|
||||||
** returned. If the input is not a keyword, TK_ID is returned.
|
** returned. If the input is not a keyword, TK_ID is returned.
|
||||||
*/
|
*/
|
||||||
static int sqliteKeywordCode(const char *z, int n){
|
int sqliteKeywordCode(const char *z, int n){
|
||||||
int h;
|
int h;
|
||||||
Keyword *p;
|
Keyword *p;
|
||||||
if( aKeywordTable[0].len==0 ){
|
if( aKeywordTable[0].len==0 ){
|
||||||
|
87
src/vdbe.c
87
src/vdbe.c
@@ -30,7 +30,7 @@
|
|||||||
** But other routines are also provided to help in building up
|
** But other routines are also provided to help in building up
|
||||||
** a program instruction by instruction.
|
** a program instruction by instruction.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.120 2002/02/19 22:42:05 drh Exp $
|
** $Id: vdbe.c,v 1.121 2002/02/21 12:01:27 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -72,6 +72,7 @@ struct Cursor {
|
|||||||
Bool keyAsData; /* The OP_Column command works on key instead of data */
|
Bool keyAsData; /* The OP_Column command works on key instead of data */
|
||||||
Bool atFirst; /* True if pointing to first entry */
|
Bool atFirst; /* True if pointing to first entry */
|
||||||
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
|
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
|
||||||
|
Bool nullRow; /* True if pointing to a row with no data */
|
||||||
Btree *pBt; /* Separate file holding temporary table */
|
Btree *pBt; /* Separate file holding temporary table */
|
||||||
};
|
};
|
||||||
typedef struct Cursor Cursor;
|
typedef struct Cursor Cursor;
|
||||||
@@ -867,30 +868,30 @@ static char *zOpName[] = { 0,
|
|||||||
"Close", "MoveTo", "NewRecno", "PutIntKey",
|
"Close", "MoveTo", "NewRecno", "PutIntKey",
|
||||||
"PutStrKey", "Distinct", "Found", "NotFound",
|
"PutStrKey", "Distinct", "Found", "NotFound",
|
||||||
"IsUnique", "NotExists", "Delete", "Column",
|
"IsUnique", "NotExists", "Delete", "Column",
|
||||||
"KeyAsData", "Recno", "FullKey", "Last",
|
"KeyAsData", "Recno", "FullKey", "NullRow",
|
||||||
"Rewind", "Next", "Destroy", "Clear",
|
"Last", "Rewind", "Next", "Destroy",
|
||||||
"CreateIndex", "CreateTable", "IntegrityCk", "IdxPut",
|
"Clear", "CreateIndex", "CreateTable", "IntegrityCk",
|
||||||
"IdxDelete", "IdxRecno", "IdxGT", "IdxGE",
|
"IdxPut", "IdxDelete", "IdxRecno", "IdxGT",
|
||||||
"MemLoad", "MemStore", "ListWrite", "ListRewind",
|
"IdxGE", "MemLoad", "MemStore", "ListWrite",
|
||||||
"ListRead", "ListReset", "SortPut", "SortMakeRec",
|
"ListRewind", "ListRead", "ListReset", "SortPut",
|
||||||
"SortMakeKey", "Sort", "SortNext", "SortCallback",
|
"SortMakeRec", "SortMakeKey", "Sort", "SortNext",
|
||||||
"SortReset", "FileOpen", "FileRead", "FileColumn",
|
"SortCallback", "SortReset", "FileOpen", "FileRead",
|
||||||
"AggReset", "AggFocus", "AggIncr", "AggNext",
|
"FileColumn", "AggReset", "AggFocus", "AggIncr",
|
||||||
"AggSet", "AggGet", "SetInsert", "SetFound",
|
"AggNext", "AggSet", "AggGet", "SetInsert",
|
||||||
"SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey",
|
"SetFound", "SetNotFound", "MakeRecord", "MakeKey",
|
||||||
"IncrKey", "Goto", "If", "Halt",
|
"MakeIdxKey", "IncrKey", "Goto", "If",
|
||||||
"ColumnCount", "ColumnName", "Callback", "NullCallback",
|
"Halt", "ColumnCount", "ColumnName", "Callback",
|
||||||
"Integer", "String", "Pop", "Dup",
|
"NullCallback", "Integer", "String", "Pop",
|
||||||
"Pull", "Push", "MustBeInt", "Add",
|
"Dup", "Pull", "Push", "MustBeInt",
|
||||||
"AddImm", "Subtract", "Multiply", "Divide",
|
"Add", "AddImm", "Subtract", "Multiply",
|
||||||
"Remainder", "BitAnd", "BitOr", "BitNot",
|
"Divide", "Remainder", "BitAnd", "BitOr",
|
||||||
"ShiftLeft", "ShiftRight", "AbsValue", "Precision",
|
"BitNot", "ShiftLeft", "ShiftRight", "AbsValue",
|
||||||
"Min", "Max", "Like", "Glob",
|
"Precision", "Min", "Max", "Like",
|
||||||
"Eq", "Ne", "Lt", "Le",
|
"Glob", "Eq", "Ne", "Lt",
|
||||||
"Gt", "Ge", "IsNull", "NotNull",
|
"Le", "Gt", "Ge", "IsNull",
|
||||||
"Negative", "And", "Or", "Not",
|
"NotNull", "Negative", "And", "Or",
|
||||||
"Concat", "Noop", "Strlen", "Substr",
|
"Not", "Concat", "Noop", "Strlen",
|
||||||
"Limit",
|
"Substr", "Limit",
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2591,6 +2592,7 @@ case OP_Open: {
|
|||||||
}
|
}
|
||||||
cleanupCursor(&p->aCsr[i]);
|
cleanupCursor(&p->aCsr[i]);
|
||||||
memset(&p->aCsr[i], 0, sizeof(Cursor));
|
memset(&p->aCsr[i], 0, sizeof(Cursor));
|
||||||
|
p->aCsr[i].nullRow = 1;
|
||||||
do{
|
do{
|
||||||
rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
|
rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
|
||||||
switch( rc ){
|
switch( rc ){
|
||||||
@@ -2648,6 +2650,7 @@ case OP_OpenTemp: {
|
|||||||
pCx = &p->aCsr[i];
|
pCx = &p->aCsr[i];
|
||||||
cleanupCursor(pCx);
|
cleanupCursor(pCx);
|
||||||
memset(pCx, 0, sizeof(*pCx));
|
memset(pCx, 0, sizeof(*pCx));
|
||||||
|
pCx->nullRow = 1;
|
||||||
rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
|
rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = sqliteBtreeBeginTrans(pCx->pBt);
|
rc = sqliteBtreeBeginTrans(pCx->pBt);
|
||||||
@@ -2708,6 +2711,7 @@ case OP_MoveTo: {
|
|||||||
sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
|
sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
|
||||||
pC->recnoIsValid = 0;
|
pC->recnoIsValid = 0;
|
||||||
}
|
}
|
||||||
|
pC->nullRow = 0;
|
||||||
sqlite_search_count++;
|
sqlite_search_count++;
|
||||||
if( res<0 ){
|
if( res<0 ){
|
||||||
sqliteBtreeNext(pC->pCursor, &res);
|
sqliteBtreeNext(pC->pCursor, &res);
|
||||||
@@ -2892,8 +2896,12 @@ case OP_NotExists: {
|
|||||||
assert( aStack[tos].flags & STK_Int );
|
assert( aStack[tos].flags & STK_Int );
|
||||||
iKey = intToKey(aStack[tos].i);
|
iKey = intToKey(aStack[tos].i);
|
||||||
rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
|
rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
|
||||||
|
p->aCsr[i].lastRecno = aStack[tos].i;
|
||||||
|
p->aCsr[i].recnoIsValid = res==0;
|
||||||
|
p->aCsr[i].nullRow = 0;
|
||||||
if( rx!=SQLITE_OK || res!=0 ){
|
if( rx!=SQLITE_OK || res!=0 ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
|
p->aCsr[i].recnoIsValid = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
@@ -2982,6 +2990,7 @@ case OP_NewRecno: {
|
|||||||
goto abort_due_to_error;
|
goto abort_due_to_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pC->recnoIsValid = 0;
|
||||||
}
|
}
|
||||||
VERIFY( NeedStack(p, p->tos+1); )
|
VERIFY( NeedStack(p, p->tos+1); )
|
||||||
p->tos++;
|
p->tos++;
|
||||||
@@ -3044,6 +3053,7 @@ case OP_PutStrKey: {
|
|||||||
}
|
}
|
||||||
rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
|
rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
|
||||||
zStack[tos], aStack[tos].n);
|
zStack[tos], aStack[tos].n);
|
||||||
|
p->aCsr[i].recnoIsValid = 0;
|
||||||
}
|
}
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
POPSTACK;
|
POPSTACK;
|
||||||
@@ -3113,7 +3123,9 @@ case OP_Column: {
|
|||||||
** is coming from the key or the data of the record.
|
** is coming from the key or the data of the record.
|
||||||
*/
|
*/
|
||||||
pCrsr = pC->pCursor;
|
pCrsr = pC->pCursor;
|
||||||
if( pC->keyAsData ){
|
if( pC->nullRow ){
|
||||||
|
payloadSize = 0;
|
||||||
|
}else if( pC->keyAsData ){
|
||||||
sqliteBtreeKeySize(pCrsr, &payloadSize);
|
sqliteBtreeKeySize(pCrsr, &payloadSize);
|
||||||
xRead = sqliteBtreeKey;
|
xRead = sqliteBtreeKey;
|
||||||
}else{
|
}else{
|
||||||
@@ -3199,6 +3211,9 @@ case OP_Recno: {
|
|||||||
int v;
|
int v;
|
||||||
if( p->aCsr[i].recnoIsValid ){
|
if( p->aCsr[i].recnoIsValid ){
|
||||||
v = p->aCsr[i].lastRecno;
|
v = p->aCsr[i].lastRecno;
|
||||||
|
}else if( p->aCsr[i].nullRow ){
|
||||||
|
aStack[tos].flags = STK_Null;
|
||||||
|
break;
|
||||||
}else{
|
}else{
|
||||||
sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v);
|
sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v);
|
||||||
v = keyToInt(v);
|
v = keyToInt(v);
|
||||||
@@ -3248,6 +3263,22 @@ case OP_FullKey: {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Opcode: NullRow P1 * *
|
||||||
|
**
|
||||||
|
** Move the cursor P1 to a null row. Any OP_Column operations
|
||||||
|
** that occur while the cursor is on the null row will always push
|
||||||
|
** a NULL onto the stack.
|
||||||
|
*/
|
||||||
|
case OP_NullRow: {
|
||||||
|
int i = pOp->p1;
|
||||||
|
BtCursor *pCrsr;
|
||||||
|
|
||||||
|
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||||
|
p->aCsr[i].nullRow = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Opcode: Last P1 P2 *
|
/* Opcode: Last P1 P2 *
|
||||||
**
|
**
|
||||||
** The next use of the Recno or Column or Next instruction for P1
|
** The next use of the Recno or Column or Next instruction for P1
|
||||||
@@ -3263,7 +3294,7 @@ case OP_Last: {
|
|||||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||||
int res;
|
int res;
|
||||||
sqliteBtreeLast(pCrsr, &res);
|
sqliteBtreeLast(pCrsr, &res);
|
||||||
p->aCsr[i].atFirst = res==0;
|
p->aCsr[i].nullRow = res;
|
||||||
if( res && pOp->p2>0 ){
|
if( res && pOp->p2>0 ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
}
|
}
|
||||||
@@ -3287,6 +3318,7 @@ case OP_Rewind: {
|
|||||||
int res;
|
int res;
|
||||||
sqliteBtreeFirst(pCrsr, &res);
|
sqliteBtreeFirst(pCrsr, &res);
|
||||||
p->aCsr[i].atFirst = res==0;
|
p->aCsr[i].atFirst = res==0;
|
||||||
|
p->aCsr[i].nullRow = res;
|
||||||
if( res && pOp->p2>0 ){
|
if( res && pOp->p2>0 ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
}
|
}
|
||||||
@@ -3308,6 +3340,7 @@ case OP_Next: {
|
|||||||
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
|
||||||
int res;
|
int res;
|
||||||
rc = sqliteBtreeNext(pCrsr, &res);
|
rc = sqliteBtreeNext(pCrsr, &res);
|
||||||
|
p->aCsr[i].nullRow = res;
|
||||||
if( res==0 ){
|
if( res==0 ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
sqlite_search_count++;
|
sqlite_search_count++;
|
||||||
|
185
src/vdbe.h
185
src/vdbe.h
@@ -15,7 +15,7 @@
|
|||||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||||
** simple program to access and modify the underlying database.
|
** simple program to access and modify the underlying database.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.h,v 1.43 2002/02/19 15:00:08 drh Exp $
|
** $Id: vdbe.h,v 1.44 2002/02/21 12:01:28 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_VDBE_H_
|
#ifndef _SQLITE_VDBE_H_
|
||||||
#define _SQLITE_VDBE_H_
|
#define _SQLITE_VDBE_H_
|
||||||
@@ -97,113 +97,114 @@ typedef struct VdbeOp VdbeOp;
|
|||||||
#define OP_KeyAsData 25
|
#define OP_KeyAsData 25
|
||||||
#define OP_Recno 26
|
#define OP_Recno 26
|
||||||
#define OP_FullKey 27
|
#define OP_FullKey 27
|
||||||
#define OP_Last 28
|
#define OP_NullRow 28
|
||||||
#define OP_Rewind 29
|
#define OP_Last 29
|
||||||
#define OP_Next 30
|
#define OP_Rewind 30
|
||||||
|
#define OP_Next 31
|
||||||
|
|
||||||
#define OP_Destroy 31
|
#define OP_Destroy 32
|
||||||
#define OP_Clear 32
|
#define OP_Clear 33
|
||||||
#define OP_CreateIndex 33
|
#define OP_CreateIndex 34
|
||||||
#define OP_CreateTable 34
|
#define OP_CreateTable 35
|
||||||
#define OP_IntegrityCk 35
|
#define OP_IntegrityCk 36
|
||||||
|
|
||||||
#define OP_IdxPut 36
|
#define OP_IdxPut 37
|
||||||
#define OP_IdxDelete 37
|
#define OP_IdxDelete 38
|
||||||
#define OP_IdxRecno 38
|
#define OP_IdxRecno 39
|
||||||
#define OP_IdxGT 39
|
#define OP_IdxGT 40
|
||||||
#define OP_IdxGE 40
|
#define OP_IdxGE 41
|
||||||
|
|
||||||
#define OP_MemLoad 41
|
#define OP_MemLoad 42
|
||||||
#define OP_MemStore 42
|
#define OP_MemStore 43
|
||||||
|
|
||||||
#define OP_ListWrite 43
|
#define OP_ListWrite 44
|
||||||
#define OP_ListRewind 44
|
#define OP_ListRewind 45
|
||||||
#define OP_ListRead 45
|
#define OP_ListRead 46
|
||||||
#define OP_ListReset 46
|
#define OP_ListReset 47
|
||||||
|
|
||||||
#define OP_SortPut 47
|
#define OP_SortPut 48
|
||||||
#define OP_SortMakeRec 48
|
#define OP_SortMakeRec 49
|
||||||
#define OP_SortMakeKey 49
|
#define OP_SortMakeKey 50
|
||||||
#define OP_Sort 50
|
#define OP_Sort 51
|
||||||
#define OP_SortNext 51
|
#define OP_SortNext 52
|
||||||
#define OP_SortCallback 52
|
#define OP_SortCallback 53
|
||||||
#define OP_SortReset 53
|
#define OP_SortReset 54
|
||||||
|
|
||||||
#define OP_FileOpen 54
|
#define OP_FileOpen 55
|
||||||
#define OP_FileRead 55
|
#define OP_FileRead 56
|
||||||
#define OP_FileColumn 56
|
#define OP_FileColumn 57
|
||||||
|
|
||||||
#define OP_AggReset 57
|
#define OP_AggReset 58
|
||||||
#define OP_AggFocus 58
|
#define OP_AggFocus 59
|
||||||
#define OP_AggIncr 59
|
#define OP_AggIncr 60
|
||||||
#define OP_AggNext 60
|
#define OP_AggNext 61
|
||||||
#define OP_AggSet 61
|
#define OP_AggSet 62
|
||||||
#define OP_AggGet 62
|
#define OP_AggGet 63
|
||||||
|
|
||||||
#define OP_SetInsert 63
|
#define OP_SetInsert 64
|
||||||
#define OP_SetFound 64
|
#define OP_SetFound 65
|
||||||
#define OP_SetNotFound 65
|
#define OP_SetNotFound 66
|
||||||
|
|
||||||
#define OP_MakeRecord 66
|
#define OP_MakeRecord 67
|
||||||
#define OP_MakeKey 67
|
#define OP_MakeKey 68
|
||||||
#define OP_MakeIdxKey 68
|
#define OP_MakeIdxKey 69
|
||||||
#define OP_IncrKey 69
|
#define OP_IncrKey 70
|
||||||
|
|
||||||
#define OP_Goto 70
|
#define OP_Goto 71
|
||||||
#define OP_If 71
|
#define OP_If 72
|
||||||
#define OP_Halt 72
|
#define OP_Halt 73
|
||||||
|
|
||||||
#define OP_ColumnCount 73
|
#define OP_ColumnCount 74
|
||||||
#define OP_ColumnName 74
|
#define OP_ColumnName 75
|
||||||
#define OP_Callback 75
|
#define OP_Callback 76
|
||||||
#define OP_NullCallback 76
|
#define OP_NullCallback 77
|
||||||
|
|
||||||
#define OP_Integer 77
|
#define OP_Integer 78
|
||||||
#define OP_String 78
|
#define OP_String 79
|
||||||
#define OP_Pop 79
|
#define OP_Pop 80
|
||||||
#define OP_Dup 80
|
#define OP_Dup 81
|
||||||
#define OP_Pull 81
|
#define OP_Pull 82
|
||||||
#define OP_Push 82
|
#define OP_Push 83
|
||||||
#define OP_MustBeInt 83
|
#define OP_MustBeInt 84
|
||||||
|
|
||||||
#define OP_Add 84
|
#define OP_Add 85
|
||||||
#define OP_AddImm 85
|
#define OP_AddImm 86
|
||||||
#define OP_Subtract 86
|
#define OP_Subtract 87
|
||||||
#define OP_Multiply 87
|
#define OP_Multiply 88
|
||||||
#define OP_Divide 88
|
#define OP_Divide 89
|
||||||
#define OP_Remainder 89
|
#define OP_Remainder 90
|
||||||
#define OP_BitAnd 90
|
#define OP_BitAnd 91
|
||||||
#define OP_BitOr 91
|
#define OP_BitOr 92
|
||||||
#define OP_BitNot 92
|
#define OP_BitNot 93
|
||||||
#define OP_ShiftLeft 93
|
#define OP_ShiftLeft 94
|
||||||
#define OP_ShiftRight 94
|
#define OP_ShiftRight 95
|
||||||
#define OP_AbsValue 95
|
#define OP_AbsValue 96
|
||||||
#define OP_Precision 96
|
#define OP_Precision 97
|
||||||
#define OP_Min 97
|
#define OP_Min 98
|
||||||
#define OP_Max 98
|
#define OP_Max 99
|
||||||
#define OP_Like 99
|
#define OP_Like 100
|
||||||
#define OP_Glob 100
|
#define OP_Glob 101
|
||||||
#define OP_Eq 101
|
#define OP_Eq 102
|
||||||
#define OP_Ne 102
|
#define OP_Ne 103
|
||||||
#define OP_Lt 103
|
#define OP_Lt 104
|
||||||
#define OP_Le 104
|
#define OP_Le 105
|
||||||
#define OP_Gt 105
|
#define OP_Gt 106
|
||||||
#define OP_Ge 106
|
#define OP_Ge 107
|
||||||
#define OP_IsNull 107
|
#define OP_IsNull 108
|
||||||
#define OP_NotNull 108
|
#define OP_NotNull 109
|
||||||
#define OP_Negative 109
|
#define OP_Negative 110
|
||||||
#define OP_And 110
|
#define OP_And 111
|
||||||
#define OP_Or 111
|
#define OP_Or 112
|
||||||
#define OP_Not 112
|
#define OP_Not 113
|
||||||
#define OP_Concat 113
|
#define OP_Concat 114
|
||||||
#define OP_Noop 114
|
#define OP_Noop 115
|
||||||
|
|
||||||
#define OP_Strlen 115
|
#define OP_Strlen 116
|
||||||
#define OP_Substr 116
|
#define OP_Substr 117
|
||||||
|
|
||||||
#define OP_Limit 117
|
#define OP_Limit 118
|
||||||
|
|
||||||
#define OP_MAX 117
|
#define OP_MAX 118
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Prototypes for the VDBE interface. See comments on the implementation
|
** Prototypes for the VDBE interface. See comments on the implementation
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the CREATE TABLE statement.
|
# focus of this file is testing the CREATE TABLE statement.
|
||||||
#
|
#
|
||||||
# $Id: table.test,v 1.14 2002/02/18 18:30:33 drh Exp $
|
# $Id: table.test,v 1.15 2002/02/21 12:01:28 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -282,8 +282,8 @@ do_test table-7.1 {
|
|||||||
desc text,
|
desc text,
|
||||||
asc text,
|
asc text,
|
||||||
explain int,
|
explain int,
|
||||||
vacuum boolean,
|
[14_vac] boolean,
|
||||||
delimiters varchar(10),
|
fuzzy_dog_12 varchar(10),
|
||||||
begin blob,
|
begin blob,
|
||||||
end clob
|
end clob
|
||||||
)
|
)
|
||||||
@@ -300,7 +300,7 @@ do_test table-7.3 {
|
|||||||
execsql2 {
|
execsql2 {
|
||||||
SELECT * FROM weird;
|
SELECT * FROM weird;
|
||||||
}
|
}
|
||||||
} {desc a asc b explain 9 vacuum 0 delimiters xyz begin hi end y'all}
|
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
|
||||||
|
|
||||||
# Try out the CREATE TABLE AS syntax
|
# Try out the CREATE TABLE AS syntax
|
||||||
#
|
#
|
||||||
@@ -309,7 +309,20 @@ do_test table-8.1 {
|
|||||||
CREATE TABLE t2 AS SELECT * FROM weird;
|
CREATE TABLE t2 AS SELECT * FROM weird;
|
||||||
SELECT * FROM t2;
|
SELECT * FROM t2;
|
||||||
}
|
}
|
||||||
} {desc a asc b explain 9 vacuum 0 delimiters xyz begin hi end y'all}
|
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
|
||||||
|
do_test table-8.1.1 {
|
||||||
|
execsql {
|
||||||
|
SELECT sql FROM sqlite_master WHERE name='t2';
|
||||||
|
}
|
||||||
|
} {{CREATE TABLE t2(
|
||||||
|
'desc',
|
||||||
|
'asc',
|
||||||
|
'explain',
|
||||||
|
'14_vac',
|
||||||
|
fuzzy_dog_12,
|
||||||
|
'begin',
|
||||||
|
'end'
|
||||||
|
)}}
|
||||||
do_test table-8.2 {
|
do_test table-8.2 {
|
||||||
execsql {
|
execsql {
|
||||||
CREATE TABLE 't3''xyz'(a,b,c);
|
CREATE TABLE 't3''xyz'(a,b,c);
|
||||||
@@ -319,10 +332,15 @@ do_test table-8.2 {
|
|||||||
} {1 2 3}
|
} {1 2 3}
|
||||||
do_test table-8.3 {
|
do_test table-8.3 {
|
||||||
execsql2 {
|
execsql2 {
|
||||||
CREATE TABLE [t4'abc] AS SELECT count(*), min(a), max(b+c) FROM [t3'xyz];
|
CREATE TABLE [t4'abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3'xyz];
|
||||||
SELECT * FROM [t4'abc];
|
SELECT * FROM [t4'abc];
|
||||||
}
|
}
|
||||||
} {count(*) 1 min(a) 1 max(b+c) 5}
|
} {cnt 1 max(b+c) 5}
|
||||||
|
do_test table-8.3.1 {
|
||||||
|
execsql {
|
||||||
|
SELECT sql FROM sqlite_master WHERE name='t4''abc'
|
||||||
|
}
|
||||||
|
} {{CREATE TABLE 't4''abc'(cnt,'max(b+c)')}}
|
||||||
do_test table-8.4 {
|
do_test table-8.4 {
|
||||||
execsql2 {
|
execsql2 {
|
||||||
CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
|
CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
|
||||||
@@ -335,16 +353,21 @@ do_test table-8.5 {
|
|||||||
execsql2 {
|
execsql2 {
|
||||||
SELECT * FROM [t4'abc];
|
SELECT * FROM [t4'abc];
|
||||||
}
|
}
|
||||||
} {count(*) 1 min(a) 1 max(b+c) 5}
|
} {cnt 1 max(b+c) 5}
|
||||||
do_test table-8.6 {
|
do_test table-8.6 {
|
||||||
execsql2 {
|
execsql2 {
|
||||||
SELECT * FROM t2;
|
SELECT * FROM t2;
|
||||||
}
|
}
|
||||||
} {desc a asc b explain 9 vacuum 0 delimiters xyz begin hi end y'all}
|
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
|
||||||
do_test table-8.7 {
|
do_test table-8.7 {
|
||||||
catchsql {
|
catchsql {
|
||||||
SELECT * FROM t5;
|
SELECT * FROM t5;
|
||||||
}
|
}
|
||||||
} {1 {no such table: t5}}
|
} {1 {no such table: t5}}
|
||||||
|
do_test table-8.8 {
|
||||||
|
catchsql {
|
||||||
|
CREATE TABLE t5 AS SELECT * FROM no_such_table;
|
||||||
|
}
|
||||||
|
} {1 {no such table: no_such_table}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@@ -23,6 +23,8 @@ chng {2002 Feb * (2.3.4)} {
|
|||||||
<li>SELECT min() or max() of an indexed column with no WHERE or GROUP BY
|
<li>SELECT min() or max() of an indexed column with no WHERE or GROUP BY
|
||||||
clause is handled as a special case which avoids a complete table scan.</li>
|
clause is handled as a special case which avoids a complete table scan.</li>
|
||||||
<li>Automatically generated ROWIDs are now sequential.</li>
|
<li>Automatically generated ROWIDs are now sequential.</li>
|
||||||
|
<li>Do not allow dot-commands of the command-line shell to occur in the
|
||||||
|
middle of a real SQL command.</li>
|
||||||
}
|
}
|
||||||
|
|
||||||
chng {2002 Feb 18 (2.3.3)} {
|
chng {2002 Feb 18 (2.3.3)} {
|
||||||
|
Reference in New Issue
Block a user