diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 6 | ||||
-rw-r--r-- | src/build.c | 133 | ||||
-rw-r--r-- | src/expr.c | 4 | ||||
-rw-r--r-- | src/insert.c | 16 | ||||
-rw-r--r-- | src/main.c | 35 | ||||
-rw-r--r-- | src/pager.c | 6 | ||||
-rw-r--r-- | src/parse.y | 60 | ||||
-rw-r--r-- | src/select.c | 6 | ||||
-rw-r--r-- | src/shell.c | 6 | ||||
-rw-r--r-- | src/sqlite.h.in | 13 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/tokenize.c | 3 | ||||
-rw-r--r-- | src/vdbe.c | 20 |
13 files changed, 234 insertions, 80 deletions
diff --git a/src/btree.c b/src/btree.c index 471cd0c74..761ccac94 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.32 2001/10/02 13:01:49 drh Exp $ +** $Id: btree.c,v 1.33 2001/10/06 16:33:02 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -595,6 +595,10 @@ static void pageDestructor(void *pData){ ** Actually, this routine just sets up the internal data structures ** for accessing the database. We do not open the database file ** until the first page is loaded. +** +** zFilename is the name of the database file. If zFilename is NULL +** a new database with a random name is created. The database will be +** destroyed when sqliteBtreeClose() is called. */ int sqliteBtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ diff --git a/src/build.c b/src/build.c index 70f0c7e2d..e8d213b43 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.43 2001/09/27 15:11:54 drh Exp $ +** $Id: build.c,v 1.44 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -203,6 +203,7 @@ void sqliteDeleteTable(sqlite *db, Table *pTable){ for(i=0; i<pTable->nCol; i++){ sqliteFree(pTable->aCol[i].zName); sqliteFree(pTable->aCol[i].zDflt); + sqliteFree(pTable->aCol[i].zType); } for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; @@ -335,7 +336,7 @@ char *sqliteTableNameFromToken(Token *pName){ ** after seeing tokens "CREATE" and "TABLE" and the table name. The ** pStart token is the CREATE and pName is the table name. ** -** The new table is constructed in files of the pParse structure. As +** The new table is constructed in fields of the pParse structure. As ** more of the CREATE TABLE statement is parsed, additional action ** routines are called to build up more of the table. */ @@ -407,6 +408,48 @@ void sqliteAddColumn(Parse *pParse, Token *pName){ } /* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. A "NOT NULL" constraint has +** been seen on a column. This routine sets the notNull flag on +** the column currently under construction. +*/ +void sqliteAddNotNull(Parse *pParse){ + Table *p; + int i; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + p->aCol[i].notNull = 1; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. The pFirst token is the first +** token in the sequence of tokens that describe the type of the +** column currently under construction. pLast is the last token +** in the sequence. Use this information to construct a string +** that contains the typename of the column and store that string +** in zType. +*/ +void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ + Table *p; + int i, j; + int n; + char *z, **pz; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + pz = &p->aCol[i].zType; + n = pLast->n + ((int)pLast->z) - (int)pFirst->z; + sqliteSetNString(pz, pFirst->z, n, 0); + z = *pz; + for(i=j=0; z[i]; i++){ + int c = z[i]; + if( isspace(c) ) continue; + z[j++] = c; + } + z[j] = 0; +} + +/* ** The given token is the default value for the last column added to ** the table currently under construction. If "minusFlag" is true, it ** means the value token was preceded by a minus sign. @@ -486,9 +529,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){ ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the root page number for the table from the ** pParse->newTnum field. (The page number should have been put - ** there by the sqliteOpenCb routine.) If the table has a primary - ** key, the root page of the index associated with the primary key - ** should be in pParse->newKnum. + ** there by the sqliteOpenCb routine.) */ if( pParse->initFlag ){ p->tnum = pParse->newTnum; @@ -618,11 +659,12 @@ void sqliteDropTable(Parse *pParse, Token *pName){ ** and pTable is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable -** as the table to be indexed. +** as the table to be indexed. pParse->pNewTable is a table that is +** currently being constructed by a CREATE TABLE statement. ** -** pList is a list of columns to be indexed. pList will be NULL if the -** most recently added column of the table is the primary key or has -** the UNIQUE constraint. +** pList is a list of columns to be indexed. pList will be NULL if this +** is a primary key or unique-constraint on the most recent column added +** to the table currently under construction. */ void sqliteCreateIndex( Parse *pParse, /* All information about this parse */ @@ -763,10 +805,9 @@ void sqliteCreateIndex( ** we don't want to recreate it. ** ** If pTable==0 it means this index is generated as a primary key - ** or UNIQUE constraint of a CREATE TABLE statement. The code generator - ** for CREATE TABLE will have already opened cursor 0 for writing to - ** the sqlite_master table and will take care of closing that cursor - ** for us in the end. So those steps are skipped when pTable==0 + ** 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. */ else if( pParse->initFlag==0 ){ int n; @@ -796,12 +837,10 @@ void sqliteCreateIndex( sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0, 0, 0); } + addr = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); if( pStart && pEnd ){ n = (int)pEnd->z - (int)pStart->z + 1; - addr = sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0); sqliteVdbeChangeP3(v, addr, pStart->z, n); - }else{ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0, 0, 0); sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0); @@ -1262,6 +1301,68 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ } }else + if( sqliteStrICmp(zLeft, "full_column_names")==0 ){ + if( getBoolean(zRight) ){ + db->flags |= SQLITE_FullColNames; + }else{ + db->flags &= ~SQLITE_FullColNames; + } + }else + + if( sqliteStrICmp(zLeft, "table_info")==0 ){ + Table *pTab; + Vdbe *v; + pTab = sqliteFindTable(db, zRight); + if( pTab ) v = sqliteGetVdbe(pParse); + if( pTab && v ){ + static VdbeOp tableInfoPreface[] = { + { OP_ColumnCount, 5, 0, 0}, + { OP_ColumnName, 0, 0, "cid"}, + { OP_ColumnName, 1, 0, "name"}, + { OP_ColumnName, 2, 0, "type"}, + { OP_ColumnName, 3, 0, "notnull"}, + { OP_ColumnName, 4, 0, "dflt_value"}, + }; + int i; + sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); + for(i=0; i<pTab->nCol; i++){ + sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[i].zName, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, + pTab->aCol[i].zType ? pTab->aCol[i].zType : "text", 0); + sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[i].zDflt, 0); + sqliteVdbeAddOp(v, OP_Callback, 5, 0, 0, 0); + } + } + }else + + if( sqliteStrICmp(zLeft, "index_info")==0 ){ + Index *pIdx; + Table *pTab; + Vdbe *v; + pIdx = sqliteFindIndex(db, zRight); + if( pIdx ) v = sqliteGetVdbe(pParse); + if( pIdx && v ){ + static VdbeOp tableInfoPreface[] = { + { OP_ColumnCount, 3, 0, 0}, + { OP_ColumnName, 0, 0, "seqno"}, + { OP_ColumnName, 1, 0, "cid"}, + { OP_ColumnName, 2, 0, "name"}, + }; + int i; + pTab = pIdx->pTable; + sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); + for(i=0; i<pIdx->nColumn; i++){ + sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0); + sqliteVdbeAddOp(v, OP_Integer, pIdx->aiColumn[i], 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, + pTab->aCol[pIdx->aiColumn[i]].zName, 0); + sqliteVdbeAddOp(v, OP_Callback, 3, 0, 0, 0); + } + } + }else + #ifndef NDEBUG if( sqliteStrICmp(zLeft, "parser_trace")==0 ){ extern void sqliteParserTrace(FILE*, char *); diff --git a/src/expr.c b/src/expr.c index 7710743f7..0bf74727a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.28 2001/09/16 00:13:27 drh Exp $ +** $Id: expr.c,v 1.29 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" @@ -526,7 +526,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ break; } case TK_NULL: { - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); break; } case TK_AND: diff --git a/src/insert.c b/src/insert.c index 1c209be2d..9529a1f9f 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.20 2001/09/27 03:22:33 drh Exp $ +** $Id: insert.c,v 1.21 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" @@ -186,12 +186,7 @@ void sqliteInsert( } } if( pColumn && j>=pColumn->nId ){ - char *zDflt = pTab->aCol[i].zDflt; - if( zDflt==0 ){ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0); - } + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[i].zDflt, 0); }else if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, i, 0, 0); }else{ @@ -218,12 +213,7 @@ void sqliteInsert( } } if( pColumn && j>=pColumn->nId ){ - char *zDflt = pTab->aCol[idx].zDflt; - if( zDflt==0 ){ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); - }else{ - sqliteVdbeAddOp(v, OP_String, 0, 0, zDflt, 0); - } + sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->aCol[idx].zDflt, 0); }else if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, idx, 0, 0); }else{ diff --git a/src/main.c b/src/main.c index 5fcc32ccc..d96aad914 100644 --- a/src/main.c +++ b/src/main.c @@ -14,14 +14,16 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.42 2001/09/27 15:11:54 drh Exp $ +** $Id: main.c,v 1.43 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** This is the callback routine for the code that initializes the -** database. Each callback contains the following information: +** database. See sqliteInit() below for additional information. +** +** Each callback contains the following information: ** ** argv[0] = "meta" or "table" or "index" ** argv[1] = table or index name or meta statement type. @@ -34,8 +36,9 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ Parse sParse; int nErr = 0; -/* TODO: Do some validity checks on all fields. In particular, -** make sure fields do not contain NULLs. */ + /* TODO: Do some validity checks on all fields. In particular, + ** make sure fields do not contain NULLs. Otherwise we might core + ** when attempting to initialize from a corrupt database file. */ assert( argc==4 ); switch( argv[0][0] ){ @@ -51,12 +54,23 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ case 'i': case 't': { /* CREATE TABLE and CREATE INDEX statements */ if( argv[3] && argv[3][0] ){ + /* Call the parser to process a CREATE TABLE or CREATE INDEX statement. + ** 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. + */ memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.initFlag = 1; sParse.newTnum = atoi(argv[2]); nErr = sqliteRunParser(&sParse, argv[3], 0); }else{ + /* If the SQL column is blank it means this is an index that + ** was created to be the PRIMARY KEY or to fulfill a UNIQUE + ** constraint or a CREATE TABLE. The index should have already + ** been created when we processed the CREATE TABLE. All we have + ** to do here is record the root page. + */ Index *pIndex = sqliteFindIndex(db, argv[1]); if( pIndex==0 || pIndex->tnum!=0 ){ nErr++; @@ -123,9 +137,12 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ ** The "tbl_name" is the name of the associated table. For tables, ** the tbl_name column is always the same as name. For indices, the ** tbl_name column contains the name of the table that the index - ** indexes. Finally, the "sql" column contains the complete text of - ** the CREATE TABLE or CREATE INDEX statement that originally created - ** the table or index. + ** indexes. The "rootpage" column holds the number of the root page + ** for the b-tree for the table or index. Finally, the "sql" column + ** contains the complete text of the CREATE TABLE or CREATE INDEX + ** statement that originally created the table or index. If an index + ** 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 @@ -175,7 +192,7 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ { OP_Goto, 0, 24, 0}, { OP_String, 0, 0, "meta"}, /* 34 */ { OP_String, 0, 0, "schema-cookie"}, - { OP_Null, 0, 0, 0}, + { OP_String, 0, 0, 0}, { OP_ReadCookie,0,0, 0}, { OP_Callback, 4, 0, 0}, { OP_Close, 0, 0, 0}, @@ -183,7 +200,7 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ }; /* Create a virtual machine to run the initialization program. Run - ** the program. The delete the virtual machine. + ** the program. Then delete the virtual machine. */ vdbe = sqliteVdbeCreate(db); if( vdbe==0 ){ diff --git a/src/pager.c b/src/pager.c index 6f60301af..6bb71efc7 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.24 2001/09/20 01:44:43 drh Exp $ +** @(#) $Id: pager.c,v 1.25 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -377,6 +377,10 @@ void sqlitepager_set_cachesize(Pager *pPager, int mxPage){ ** The file to be cached need not exist. The file is not locked until ** the first call to sqlitepager_get() and is only held open until the ** last page is released using sqlitepager_unref(). +** +** If zFilename is NULL then a random temporary file is created and used +** as the file to be cached. The file will be deleted automatically when +** it is closed. */ int sqlitepager_open( Pager **ppPager, /* Return the Pager structure here */ diff --git a/src/parse.y b/src/parse.y index d64c56ba3..56e6af75a 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.33 2001/10/01 14:29:23 drh Exp $ +** @(#) $Id: parse.y,v 1.34 2001/10/06 16:33:03 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -49,9 +49,7 @@ ecmd ::= cmd. {sqliteExec(pParse);} ecmd ::= . explain ::= EXPLAIN. {pParse->explain = 1;} -// Begin and end transactions. Transaction support is sparse. -// Some backends support only COMMIT and not ROLLBACK. There can -// be only a single active transaction at a time. +///////////////////// Begin and end transactions. //////////////////////////// // cmd ::= BEGIN trans_opt. {sqliteBeginTransaction(pParse);} trans_opt ::= . @@ -61,7 +59,7 @@ cmd ::= COMMIT trans_opt. {sqliteCommitTransaction(pParse);} cmd ::= END trans_opt. {sqliteCommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqliteRollbackTransaction(pParse);} -// The first form of a command is a CREATE TABLE statement. +///////////////////// The CREATE TABLE statement //////////////////////////// // cmd ::= create_table create_table_args. create_table ::= CREATE(X) TABLE ids(Y). {sqliteStartTable(pParse,&X,&Y);} @@ -79,7 +77,8 @@ columnid ::= ids(X). {sqliteAddColumn(pParse,&X);} // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. -// We also make DESC and identifier since it comes up so often. +// We also make DESC and identifier since it comes up so often (as +// an abbreviation of "description"). // %type id {Token} id(A) ::= DESC(X). {A = X;} @@ -99,11 +98,14 @@ id(A) ::= ID(X). {A = X;} ids(A) ::= id(X). {A = X;} ids(A) ::= STRING(X). {A = X;} -type ::= typename. -type ::= typename LP signed RP. -type ::= typename LP signed COMMA signed RP. -typename ::= ids. -typename ::= typename ids. +type ::= . +type ::= typename(X). {sqliteAddColumnType(pParse,&X,&X);} +type ::= typename(X) LP signed RP(Y). {sqliteAddColumnType(pParse,&X,&Y);} +type ::= typename(X) LP signed COMMA signed RP(Y). + {sqliteAddColumnType(pParse,&X,&Y);} +%type typename {Token} +typename(A) ::= ids(X). {A = X;} +typename(A) ::= typename(X) ids. {A = X;} signed ::= INTEGER. signed ::= PLUS INTEGER. signed ::= MINUS INTEGER. @@ -121,15 +123,16 @@ carg ::= DEFAULT PLUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,0);} carg ::= DEFAULT MINUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,1);} carg ::= DEFAULT NULL. -// In addition to the type name, we also care about the primary key. +// In addition to the type name, we also care about the primary key and +// UNIQUE constraints. // -ccons ::= NOT NULL. +ccons ::= NOT NULL. {sqliteAddNotNull(pParse);} ccons ::= PRIMARY KEY sortorder. {sqliteCreateIndex(pParse,0,0,0,1,0,0);} ccons ::= UNIQUE. {sqliteCreateIndex(pParse,0,0,0,1,0,0);} ccons ::= CHECK LP expr RP. // For the time being, the only constraint we care about is the primary -// key. +// key and UNIQUE. Both create indices. // conslist_opt ::= . conslist_opt ::= COMMA conslist. @@ -140,14 +143,12 @@ tcons ::= CONSTRAINT ids. tcons ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);} tcons ::= UNIQUE LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);} tcons ::= CHECK expr. -// idlist ::= idlist COMMA ids. -// idlist ::= ids. -// The next command format is dropping tables. +////////////////////////// The DROP TABLE ///////////////////////////////////// // cmd ::= DROP TABLE ids(X). {sqliteDropTable(pParse,&X);} -// The select statement +//////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { sqliteSelect(pParse, X, SRT_Callback, 0); @@ -253,7 +254,8 @@ groupby_opt(A) ::= GROUP BY exprlist(X). {A = X;} having_opt(A) ::= . {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} - +/////////////////////////// The DELETE statement ///////////////////////////// +// cmd ::= DELETE FROM ids(X) where_opt(Y). {sqliteDeleteFrom(pParse, &X, Y);} @@ -266,6 +268,8 @@ where_opt(A) ::= WHERE expr(X). {A = X;} %type setlist {ExprList*} %destructor setlist {sqliteExprListDelete($$);} +////////////////////////// The UPDATE command //////////////////////////////// +// cmd ::= UPDATE ids(X) SET setlist(Y) where_opt(Z). {sqliteUpdate(pParse,&X,Y,Z);} @@ -273,6 +277,8 @@ setlist(A) ::= setlist(Z) COMMA ids(X) EQ expr(Y). {A = sqliteExprListAppend(Z,Y,&X);} setlist(A) ::= ids(X) EQ expr(Y). {A = sqliteExprListAppend(0,Y,&X);} +////////////////////////// The INSERT command ///////////////////////////////// +// cmd ::= INSERT INTO ids(X) inscollist_opt(F) VALUES LP itemlist(Y) RP. {sqliteInsert(pParse, &X, Y, 0, F);} cmd ::= INSERT INTO ids(X) inscollist_opt(F) select(S). @@ -311,6 +317,8 @@ inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;} inscollist(A) ::= inscollist(X) COMMA ids(Y). {A = sqliteIdListAppend(X,&Y);} inscollist(A) ::= ids(Y). {A = sqliteIdListAppend(0,&Y);} +/////////////////////////// Expression Processing ///////////////////////////// +// %left OR. %left AND. %right NOT. @@ -452,7 +460,8 @@ exprlist(A) ::= expritem(X). {A = sqliteExprListAppend(0,X,0);} expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} - +///////////////////////////// The CREATE INDEX command /////////////////////// +// cmd ::= CREATE(S) uniqueflag(U) INDEX ids(X) ON ids(Y) LP idxlist(Z) RP(E). {sqliteCreateIndex(pParse, &X, &Y, Z, U, &S, &E);} @@ -470,20 +479,31 @@ idxlist(A) ::= idxitem(Y). {A = sqliteIdListAppend(0,&Y);} idxitem(A) ::= ids(X). {A = X;} +///////////////////////////// The CREATE INDEX command /////////////////////// +// + cmd ::= DROP INDEX ids(X). {sqliteDropIndex(pParse, &X);} + +///////////////////////////// The DROP INDEX command ///////////////////////// +// cmd ::= COPY ids(X) FROM ids(Y) USING DELIMITERS STRING(Z). {sqliteCopy(pParse,&X,&Y,&Z);} cmd ::= COPY ids(X) FROM ids(Y). {sqliteCopy(pParse,&X,&Y,0);} +///////////////////////////// The VACUUM command ///////////////////////////// +// cmd ::= VACUUM. {sqliteVacuum(pParse,0);} cmd ::= VACUUM ids(X). {sqliteVacuum(pParse,&X);} +///////////////////////////// The PRAGMA command ///////////////////////////// +// cmd ::= PRAGMA ids(X) EQ ids(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ ON(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ plus_num(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ minus_num(Y). {sqlitePragma(pParse,&X,&Y,1);} +cmd ::= PRAGMA ids(X) LP ids(Y) RP. {sqlitePragma(pParse,&X,&Y,0);} plus_num(A) ::= plus_opt number(X). {A = X;} minus_num(A) ::= MINUS number(X). {A = X;} number(A) ::= INTEGER(X). {A = X;} diff --git a/src/select.c b/src/select.c index 7b9c47942..ab1cc5a27 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.37 2001/09/16 00:13:27 drh Exp $ +** $Id: select.c,v 1.38 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" @@ -250,7 +250,7 @@ void generateColumnNames(Parse *pParse, IdList *pTabList, ExprList *pEList){ sprintf(zName, "column%d", i+1); sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0); }else{ - if( pTabList->nId>1 ){ + if( pTabList->nId>1 || (pParse->db->flags & SQLITE_FullColNames)!=0 ){ char *zName = 0; Table *pTab = pTabList->a[p->iTable].pTab; char *zTab; @@ -861,7 +861,7 @@ int sqliteSelect( /* Initialize the memory cell to NULL */ if( eDest==SRT_Mem ){ - sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); + sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0); } diff --git a/src/shell.c b/src/shell.c index a9f34e110..726dd9261 100644 --- a/src/shell.c +++ b/src/shell.c @@ -12,13 +12,12 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.35 2001/10/01 14:29:23 drh Exp $ +** $Id: shell.c,v 1.36 2001/10/06 16:33:03 drh Exp $ */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include "sqlite.h" -#include <unistd.h> #include <ctype.h> #ifdef OS_UNIX # include <signal.h> @@ -603,8 +602,6 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ }else if( strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; }else if( strncmp(azArg[1],"insert",n2)==0 ){ - char *zTab; - int k, n; p->mode = MODE_Insert; if( nArg>=3 ){ set_table_name(p, azArg[2]); @@ -908,6 +905,7 @@ int main(int argc, char **argv){ exit(1); } }else{ + extern int isatty(); if( isatty(0) ){ printf( "SQLite version %s\n" diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9056ed456..4bf2fdd4d 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.20 2001/09/27 03:22:33 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.21 2001/10/06 16:33:03 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -24,6 +24,13 @@ #define SQLITE_VERSION "--VERS--" /* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from ** the same version. @@ -342,4 +349,8 @@ int sqlite_get_table_vprintf( va_list ap /* Arguments to the format string */ ); +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif + #endif /* _SQLITE_H_ */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5d1d7438f..59f0a2557 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.56 2001/09/27 15:11:54 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.57 2001/10/06 16:33:03 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -164,6 +164,7 @@ struct sqlite { #define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ #define SQLITE_InTrans 0x00000008 /* True if in a transaction */ #define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ /* ** Current file format version @@ -177,6 +178,7 @@ struct sqlite { struct Column { char *zName; /* Name of this column */ char *zDflt; /* Default value of this column */ + char *zType; /* Data type for this column */ int notNull; /* True if there is a NOT NULL constraint */ }; @@ -423,6 +425,8 @@ void sqliteCommitInternalChanges(sqlite*); void sqliteRollbackInternalChanges(sqlite*); void sqliteStartTable(Parse*,Token*,Token*); void sqliteAddColumn(Parse*,Token*); +void sqliteAddNotNull(Parse*); +void sqliteAddColumnType(Parse*,Token*,Token*); void sqliteAddDefaultValue(Parse*,Token*,int); void sqliteEndTable(Parse*,Token*); void sqliteDropTable(Parse*, Token*); diff --git a/src/tokenize.c b/src/tokenize.c index 53ebbbf1a..619ae6ea9 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.23 2001/09/23 02:35:53 drh Exp $ +** $Id: tokenize.c,v 1.24 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -333,7 +333,6 @@ int sqliteRunParser(Parse *pParse, char *zSql, char **pzErrMsg){ } switch( tokenType ){ case TK_SPACE: - break; case TK_COMMENT: { break; } diff --git a/src/vdbe.c b/src/vdbe.c index 546b7bf86..0e2614bcb 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,11 +30,10 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.79 2001/09/27 15:11:54 drh Exp $ +** $Id: vdbe.c,v 1.80 2001/10/06 16:33:03 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> -#include <unistd.h> /* ** SQL is translated into a sequence of instructions to be @@ -1084,20 +1083,26 @@ case OP_Integer: { /* Opcode: String * * P3 ** -** The string value P3 is pushed onto the stack. +** The string value P3 is pushed onto the stack. If P3==0 then a +** NULL is pushed onto the stack. */ case OP_String: { int i = ++p->tos; char *z; VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) z = pOp->p3; - if( z==0 ) z = ""; - zStack[i] = z; - aStack[i].n = strlen(z) + 1; - aStack[i].flags = STK_Str; + if( z==0 ){ + zStack[i] = 0; + aStack[i].flags = STK_Null; + }else{ + zStack[i] = z; + aStack[i].n = strlen(z) + 1; + aStack[i].flags = STK_Str; + } break; } +#if 0 /* NOT USED */ /* Opcode: Null * * * ** ** Push a NULL value onto the stack. @@ -1109,6 +1114,7 @@ case OP_Null: { aStack[i].flags = STK_Null; break; } +#endif /* Opcode: Pop P1 * * ** |