-C Do\snot\sallow\sdot-commands\sto\soccur\sin\sthe\smiddle\sof\sa\sreal\sSQL\scommand.\s(CVS\s385)
-D 2002-02-21T02:25:03
+C Change\sthe\sSQLITE_MASTER\sformat\sto\sversion\s2\sin\spreparation\sfor\sadding\sviews.\s(CVS\s386)
+D 2002-02-21T12:01:27
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c 495275fe14f3b718cf2f691dce979d4c0e1f8e5d
F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
-F src/build.c 088acf87a92b00edda1206ccafac3518660b1b3b
+F src/build.c 4e10d8e61971fe900317d00a98f49dd7ceb27c20
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
F src/expr.c 7aff65ea0732b07d36925087ad611019103ad69a
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
F src/hash.h d1ce47900c7325af5e41c4feb4855c4bf2b841e7
F src/insert.c eae5aa2e9ac68c4d465e71b2ad34bcbb882979cf
-F src/main.c fada622b468c54fb211372f38a27ee636915e2ee
+F src/main.c abc0732d4caa676ff8337f278b01f1f1b57538f5
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c f6bc9b7ab530346bb7fef2ed39f2f1f214bc14ea
F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6
F src/parse.y b82278917959eefd05bd08c90e07a4fa5917ea51
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
-F src/select.c 282f37b2fdb9367f0230811e1cf7bba48665fb72
+F src/select.c f0cbfd2d9059e0f33837797ee326fbe964a35f09
F src/shell.c cbf48bf0ca35c4e0d8a7d2a86f7724f52c525cd7
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
-F src/sqliteInt.h e19efd5b1c6accfb3418cbb5c0e8c143fc1d18d7
+F src/sqliteInt.h 338cd586b9322105080a2a31122446e504ac1fc4
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
-F src/tokenize.c 9e98f94469694a763992860596137e78dbae0cc0
+F src/tokenize.c 777b734f9d06f5a9055b6808e5baec18936a4fd9
F src/update.c 95459f94a061860bf8e5716b3426a5ba85c79103
F src/util.c f31f3d6198a0d1296a16f5a6ceec423a932cbbf6
-F src/vdbe.c 18b6e9ed3bcdd76ae74d60a977a6d8a3a1b0f797
-F src/vdbe.h b4d35e159fbb80a74728b4a96e5b789fffce6f57
+F src/vdbe.c 44832d804e109248e9e2abd40daee5f8ac735450
+F src/vdbe.h 002bb8cf884034bea25a9fe901a9c5e9d29bc045
F src/where.c f79bc3179379b46b131a67ab10713779368dceee
F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/select6.test d9fb417d6cab75a072b547ba6303120f327fd6fd
F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b
F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78
-F test/table.test b8be4d3d3ff6b4858516fa274d38075ba06b5004
+F test/table.test 17b0b6eafa3faaee5545b7a94e6c1ff73f0880f3
F test/tableapi.test 51d0c209aa6b1158cb952ec917c656d4ce66e9e4
F test/tclsqlite.test ca8dd89b02ab68bd4540163c24551756a69f6783
F test/temptable.test 0e9934283259a5e637eec756a7eefd6964c0f79b
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
F www/c_interface.tcl 63efc40f09e2f0d8fea43d174103248b160fdf0e
-F www/changes.tcl e9ac5ffc030ad355fb5973bc2c68e622c3bc9ae2
+F www/changes.tcl 4aee975940a59d43736cdd4cd352c51e1e6426ba
F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
F www/download.tcl a6d75b8b117cd33dcb090bef7e80d7556d28ebe0
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 953928537c350e6c9df157553114c6d9d44712d5
-R 9ed6435fa0cf461ec879e5b28166d8d6
+P ffb00bf36a9a5851ea4a69f9c7dd7ce412553e3b
+R 827e990a5d306ede002baf12f96964e4
U drh
-Z a1b5da6dd8cc3bb5ba9dca0ec016a36c
+Z 93dfb9234ed5554b3f3a0a3a7b0ddf3a
-ffb00bf36a9a5851ea4a69f9c7dd7ce412553e3b
\ No newline at end of file
+b2a9807fed544e83002366149b9a363759338c5d
\ No newline at end of file
** ROLLBACK
** 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 <ctype.h>
pTable->isTemp = isTemp;
if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
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 ){
sqliteBeginWriteOperation(pParse);
if( !isTemp ){
sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
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);
}
}
}
*/
static int identLength(const char *z){
int n;
- for(n=2; *z; n++, z++){
- if( *z=='\'' ){ n++; }
+ int needQuote = 0;
+ for(n=0; *z; n++, z++){
+ if( *z=='\'' ){ n++; needQuote=1; }
}
- return n;
+ return n + needQuote*2;
}
/*
** quote characters as needed.
*/
static void identPut(char *z, int *pIdx, char *zIdent){
- int i, j;
+ int i, j, needQuote;
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++){
z[i++] = zIdent[j];
if( zIdent[j]=='\'' ) z[i++] = '\'';
}
- z[i++] = '\'';
+ if( needQuote ) z[i++] = '\'';
z[i] = 0;
*pIdx = i;
}
*/
if( pSelect ){
Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
+ if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
}
/* 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
** make an entry in SQLITE_MASTER.
sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
p->tnum = 0;
if( !p->isTemp ){
- sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
+ sqliteVdbeAddOp(v, OP_Pull, 1, 0);
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
sqliteVdbeAddOp(v, OP_String, 0, 0);
** other files are for internal use by SQLite and should not be
** 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 "os.h"
db->next_cookie = db->schema_cookie;
break;
}
+ case 'v':
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] ){
- /* 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
** 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));
sParse.db = db;
** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table,
** then the "sql" column is NULL.
**
- ** If the "type" column has the value "meta", then the "sql" column
- ** contains extra information about the database, such as the
- ** file format version number. All meta information must be processed
- ** before any tables or indices are constructed.
+ ** In format 1, entries in the sqlite_master table are in a random
+ ** order. Two passes must be made through the table to initialize
+ ** internal data structures. The first pass reads table definitions
+ ** 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
** table then goes back and invokes the callback on the
** database scheme.
*/
static VdbeOp initProg[] = {
+ /* Send the file format to the callback routine
+ */
{ OP_Open, 0, 2, 0},
{ OP_String, 0, 0, "file-format"},
{ OP_String, 0, 0, 0},
{ OP_String, 0, 0, 0},
{ OP_ReadCookie, 0, 1, 0},
{ OP_Callback, 4, 0, 0},
+
+ /* Send the initial schema cookie to the callback
+ */
{ OP_String, 0, 0, "schema_cookie"},
{ OP_String, 0, 0, 0},
{ OP_String, 0, 0, 0},
{ OP_ReadCookie, 0, 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_Ne, 0, 20, 0},
+ { OP_Ne, 0, 32, 0},
{ OP_Column, 0, 0, 0},
{ OP_Column, 0, 1, 0},
{ OP_Column, 0, 3, 0},
{ OP_Column, 0, 4, 0},
{ OP_Callback, 4, 0, 0},
- { OP_Next, 0, 12, 0}, /* 20 */
- { OP_Rewind, 0, 31, 0}, /* 21 */
- { OP_Column, 0, 0, 0}, /* 22 */
+ { OP_Next, 0, 24, 0}, /* 32 */
+ { OP_Rewind, 0, 43, 0}, /* 33 */
+ { OP_Column, 0, 0, 0}, /* 34 */
{ OP_String, 0, 0, "index"},
- { OP_Ne, 0, 30, 0},
+ { OP_Ne, 0, 42, 0},
{ OP_Column, 0, 0, 0},
{ OP_Column, 0, 1, 0},
{ OP_Column, 0, 3, 0},
{ OP_Column, 0, 4, 0},
{ OP_Callback, 4, 0, 0},
- { OP_Next, 0, 22, 0}, /* 30 */
- { OP_Close, 0, 0, 0}, /* 31 */
+ { OP_Next, 0, 34, 0}, /* 42 */
+ { OP_Close, 0, 0, 0}, /* 43 */
{ OP_Halt, 0, 0, 0},
};
db->pBusyArg, db->xBusyCallback);
sqliteVdbeDelete(vdbe);
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);
rc = SQLITE_ERROR;
}
** This file contains C code routines that are called by the parser
** 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"
pTab = p->pSrc->a[0].pTab;
/* 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 ){
pIdx = 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.
*/
v = sqliteGetVdbe(pParse);
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 ){
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
*************************************************************************
** 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 "hash.h"
#define MAX_PAGES 100
#define TEMP_PAGES 25
-/*
-** File format version number
-*/
-#define FILE_FORMAT 1
-
/*
** Integers of known sizes. These typedefs might change for architectures
** where the sizes very. Preprocessor macros are available so that the
void sqliteSetString(char **, const char *, ...);
void sqliteSetNString(char **, ...);
void sqliteDequote(char*);
+int sqliteKeywordCode(const char*, int);
int sqliteRunParser(Parse*, const char*, char **);
void sqliteExec(Parse*);
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
** individual tokens and sends those tokens one-by-one over to the
** 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 "os.h"
** 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.
*/
-static int sqliteKeywordCode(const char *z, int n){
+int sqliteKeywordCode(const char *z, int n){
int h;
Keyword *p;
if( aKeywordTable[0].len==0 ){
** But other routines are also provided to help in building up
** 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 <ctype.h>
Bool keyAsData; /* The OP_Column command works on key instead of data */
Bool atFirst; /* True if pointing to first entry */
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 */
};
typedef struct Cursor Cursor;
"Close", "MoveTo", "NewRecno", "PutIntKey",
"PutStrKey", "Distinct", "Found", "NotFound",
"IsUnique", "NotExists", "Delete", "Column",
- "KeyAsData", "Recno", "FullKey", "Last",
- "Rewind", "Next", "Destroy", "Clear",
- "CreateIndex", "CreateTable", "IntegrityCk", "IdxPut",
- "IdxDelete", "IdxRecno", "IdxGT", "IdxGE",
- "MemLoad", "MemStore", "ListWrite", "ListRewind",
- "ListRead", "ListReset", "SortPut", "SortMakeRec",
- "SortMakeKey", "Sort", "SortNext", "SortCallback",
- "SortReset", "FileOpen", "FileRead", "FileColumn",
- "AggReset", "AggFocus", "AggIncr", "AggNext",
- "AggSet", "AggGet", "SetInsert", "SetFound",
- "SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey",
- "IncrKey", "Goto", "If", "Halt",
- "ColumnCount", "ColumnName", "Callback", "NullCallback",
- "Integer", "String", "Pop", "Dup",
- "Pull", "Push", "MustBeInt", "Add",
- "AddImm", "Subtract", "Multiply", "Divide",
- "Remainder", "BitAnd", "BitOr", "BitNot",
- "ShiftLeft", "ShiftRight", "AbsValue", "Precision",
- "Min", "Max", "Like", "Glob",
- "Eq", "Ne", "Lt", "Le",
- "Gt", "Ge", "IsNull", "NotNull",
- "Negative", "And", "Or", "Not",
- "Concat", "Noop", "Strlen", "Substr",
- "Limit",
+ "KeyAsData", "Recno", "FullKey", "NullRow",
+ "Last", "Rewind", "Next", "Destroy",
+ "Clear", "CreateIndex", "CreateTable", "IntegrityCk",
+ "IdxPut", "IdxDelete", "IdxRecno", "IdxGT",
+ "IdxGE", "MemLoad", "MemStore", "ListWrite",
+ "ListRewind", "ListRead", "ListReset", "SortPut",
+ "SortMakeRec", "SortMakeKey", "Sort", "SortNext",
+ "SortCallback", "SortReset", "FileOpen", "FileRead",
+ "FileColumn", "AggReset", "AggFocus", "AggIncr",
+ "AggNext", "AggSet", "AggGet", "SetInsert",
+ "SetFound", "SetNotFound", "MakeRecord", "MakeKey",
+ "MakeIdxKey", "IncrKey", "Goto", "If",
+ "Halt", "ColumnCount", "ColumnName", "Callback",
+ "NullCallback", "Integer", "String", "Pop",
+ "Dup", "Pull", "Push", "MustBeInt",
+ "Add", "AddImm", "Subtract", "Multiply",
+ "Divide", "Remainder", "BitAnd", "BitOr",
+ "BitNot", "ShiftLeft", "ShiftRight", "AbsValue",
+ "Precision", "Min", "Max", "Like",
+ "Glob", "Eq", "Ne", "Lt",
+ "Le", "Gt", "Ge", "IsNull",
+ "NotNull", "Negative", "And", "Or",
+ "Not", "Concat", "Noop", "Strlen",
+ "Substr", "Limit",
};
/*
}
cleanupCursor(&p->aCsr[i]);
memset(&p->aCsr[i], 0, sizeof(Cursor));
+ p->aCsr[i].nullRow = 1;
do{
rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
switch( rc ){
pCx = &p->aCsr[i];
cleanupCursor(pCx);
memset(pCx, 0, sizeof(*pCx));
+ pCx->nullRow = 1;
rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
if( rc==SQLITE_OK ){
rc = sqliteBtreeBeginTrans(pCx->pBt);
sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
pC->recnoIsValid = 0;
}
+ pC->nullRow = 0;
sqlite_search_count++;
if( res<0 ){
sqliteBtreeNext(pC->pCursor, &res);
assert( aStack[tos].flags & STK_Int );
iKey = intToKey(aStack[tos].i);
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 ){
- pc = pOp->p2 - 1;
+ pc = pOp->p2 - 1;
+ p->aCsr[i].recnoIsValid = 0;
}
}
POPSTACK;
goto abort_due_to_error;
}
}
+ pC->recnoIsValid = 0;
}
VERIFY( NeedStack(p, p->tos+1); )
p->tos++;
}
rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
zStack[tos], aStack[tos].n);
+ p->aCsr[i].recnoIsValid = 0;
}
POPSTACK;
POPSTACK;
** is coming from the key or the data of the record.
*/
pCrsr = pC->pCursor;
- if( pC->keyAsData ){
+ if( pC->nullRow ){
+ payloadSize = 0;
+ }else if( pC->keyAsData ){
sqliteBtreeKeySize(pCrsr, &payloadSize);
xRead = sqliteBtreeKey;
}else{
int v;
if( p->aCsr[i].recnoIsValid ){
v = p->aCsr[i].lastRecno;
+ }else if( p->aCsr[i].nullRow ){
+ aStack[tos].flags = STK_Null;
+ break;
}else{
sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v);
v = keyToInt(v);
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 *
**
** The next use of the Recno or Column or Next instruction for P1
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res;
sqliteBtreeLast(pCrsr, &res);
- p->aCsr[i].atFirst = res==0;
+ p->aCsr[i].nullRow = res;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
int res;
sqliteBtreeFirst(pCrsr, &res);
p->aCsr[i].atFirst = res==0;
+ p->aCsr[i].nullRow = res;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res;
rc = sqliteBtreeNext(pCrsr, &res);
+ p->aCsr[i].nullRow = res;
if( res==0 ){
pc = pOp->p2 - 1;
sqlite_search_count++;
** or VDBE. The VDBE implements an abstract machine that runs a
** 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_
#define _SQLITE_VDBE_H_
#define OP_KeyAsData 25
#define OP_Recno 26
#define OP_FullKey 27
-#define OP_Last 28
-#define OP_Rewind 29
-#define OP_Next 30
-
-#define OP_Destroy 31
-#define OP_Clear 32
-#define OP_CreateIndex 33
-#define OP_CreateTable 34
-#define OP_IntegrityCk 35
-
-#define OP_IdxPut 36
-#define OP_IdxDelete 37
-#define OP_IdxRecno 38
-#define OP_IdxGT 39
-#define OP_IdxGE 40
-
-#define OP_MemLoad 41
-#define OP_MemStore 42
-
-#define OP_ListWrite 43
-#define OP_ListRewind 44
-#define OP_ListRead 45
-#define OP_ListReset 46
-
-#define OP_SortPut 47
-#define OP_SortMakeRec 48
-#define OP_SortMakeKey 49
-#define OP_Sort 50
-#define OP_SortNext 51
-#define OP_SortCallback 52
-#define OP_SortReset 53
-
-#define OP_FileOpen 54
-#define OP_FileRead 55
-#define OP_FileColumn 56
-
-#define OP_AggReset 57
-#define OP_AggFocus 58
-#define OP_AggIncr 59
-#define OP_AggNext 60
-#define OP_AggSet 61
-#define OP_AggGet 62
-
-#define OP_SetInsert 63
-#define OP_SetFound 64
-#define OP_SetNotFound 65
-
-#define OP_MakeRecord 66
-#define OP_MakeKey 67
-#define OP_MakeIdxKey 68
-#define OP_IncrKey 69
-
-#define OP_Goto 70
-#define OP_If 71
-#define OP_Halt 72
-
-#define OP_ColumnCount 73
-#define OP_ColumnName 74
-#define OP_Callback 75
-#define OP_NullCallback 76
-
-#define OP_Integer 77
-#define OP_String 78
-#define OP_Pop 79
-#define OP_Dup 80
-#define OP_Pull 81
-#define OP_Push 82
-#define OP_MustBeInt 83
-
-#define OP_Add 84
-#define OP_AddImm 85
-#define OP_Subtract 86
-#define OP_Multiply 87
-#define OP_Divide 88
-#define OP_Remainder 89
-#define OP_BitAnd 90
-#define OP_BitOr 91
-#define OP_BitNot 92
-#define OP_ShiftLeft 93
-#define OP_ShiftRight 94
-#define OP_AbsValue 95
-#define OP_Precision 96
-#define OP_Min 97
-#define OP_Max 98
-#define OP_Like 99
-#define OP_Glob 100
-#define OP_Eq 101
-#define OP_Ne 102
-#define OP_Lt 103
-#define OP_Le 104
-#define OP_Gt 105
-#define OP_Ge 106
-#define OP_IsNull 107
-#define OP_NotNull 108
-#define OP_Negative 109
-#define OP_And 110
-#define OP_Or 111
-#define OP_Not 112
-#define OP_Concat 113
-#define OP_Noop 114
-
-#define OP_Strlen 115
-#define OP_Substr 116
-
-#define OP_Limit 117
-
-#define OP_MAX 117
+#define OP_NullRow 28
+#define OP_Last 29
+#define OP_Rewind 30
+#define OP_Next 31
+
+#define OP_Destroy 32
+#define OP_Clear 33
+#define OP_CreateIndex 34
+#define OP_CreateTable 35
+#define OP_IntegrityCk 36
+
+#define OP_IdxPut 37
+#define OP_IdxDelete 38
+#define OP_IdxRecno 39
+#define OP_IdxGT 40
+#define OP_IdxGE 41
+
+#define OP_MemLoad 42
+#define OP_MemStore 43
+
+#define OP_ListWrite 44
+#define OP_ListRewind 45
+#define OP_ListRead 46
+#define OP_ListReset 47
+
+#define OP_SortPut 48
+#define OP_SortMakeRec 49
+#define OP_SortMakeKey 50
+#define OP_Sort 51
+#define OP_SortNext 52
+#define OP_SortCallback 53
+#define OP_SortReset 54
+
+#define OP_FileOpen 55
+#define OP_FileRead 56
+#define OP_FileColumn 57
+
+#define OP_AggReset 58
+#define OP_AggFocus 59
+#define OP_AggIncr 60
+#define OP_AggNext 61
+#define OP_AggSet 62
+#define OP_AggGet 63
+
+#define OP_SetInsert 64
+#define OP_SetFound 65
+#define OP_SetNotFound 66
+
+#define OP_MakeRecord 67
+#define OP_MakeKey 68
+#define OP_MakeIdxKey 69
+#define OP_IncrKey 70
+
+#define OP_Goto 71
+#define OP_If 72
+#define OP_Halt 73
+
+#define OP_ColumnCount 74
+#define OP_ColumnName 75
+#define OP_Callback 76
+#define OP_NullCallback 77
+
+#define OP_Integer 78
+#define OP_String 79
+#define OP_Pop 80
+#define OP_Dup 81
+#define OP_Pull 82
+#define OP_Push 83
+#define OP_MustBeInt 84
+
+#define OP_Add 85
+#define OP_AddImm 86
+#define OP_Subtract 87
+#define OP_Multiply 88
+#define OP_Divide 89
+#define OP_Remainder 90
+#define OP_BitAnd 91
+#define OP_BitOr 92
+#define OP_BitNot 93
+#define OP_ShiftLeft 94
+#define OP_ShiftRight 95
+#define OP_AbsValue 96
+#define OP_Precision 97
+#define OP_Min 98
+#define OP_Max 99
+#define OP_Like 100
+#define OP_Glob 101
+#define OP_Eq 102
+#define OP_Ne 103
+#define OP_Lt 104
+#define OP_Le 105
+#define OP_Gt 106
+#define OP_Ge 107
+#define OP_IsNull 108
+#define OP_NotNull 109
+#define OP_Negative 110
+#define OP_And 111
+#define OP_Or 112
+#define OP_Not 113
+#define OP_Concat 114
+#define OP_Noop 115
+
+#define OP_Strlen 116
+#define OP_Substr 117
+
+#define OP_Limit 118
+
+#define OP_MAX 118
/*
** Prototypes for the VDBE interface. See comments on the implementation
# This file implements regression tests for SQLite library. The
# 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]
source $testdir/tester.tcl
desc text,
asc text,
explain int,
- vacuum boolean,
- delimiters varchar(10),
+ [14_vac] boolean,
+ fuzzy_dog_12 varchar(10),
begin blob,
end clob
)
execsql2 {
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
#
CREATE TABLE t2 AS SELECT * FROM weird;
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 {
execsql {
CREATE TABLE 't3''xyz'(a,b,c);
} {1 2 3}
do_test table-8.3 {
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];
}
-} {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 {
execsql2 {
CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
execsql2 {
SELECT * FROM [t4'abc];
}
-} {count(*) 1 min(a) 1 max(b+c) 5}
+} {cnt 1 max(b+c) 5}
do_test table-8.6 {
execsql2 {
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 {
catchsql {
SELECT * FROM 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
<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>
<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)} {