Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | :-) (CVS 15) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8d66c7355de1d87b25c4fb92d0ef3603 |
User & Date: | drh 2000-05-30 16:27:04.000 |
Context
2000-05-30
| ||
17:30 | :-) (CVS 16) (check-in: b56d1b9c0f user: drh tags: trunk) | |
16:27 | :-) (CVS 15) (check-in: 8d66c7355d user: drh tags: trunk) | |
13:44 | :-) (CVS 14) (check-in: 1bb8ee8d9f user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** when syntax rules are reduced. ** | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** when syntax rules are reduced. ** ** $Id: build.c,v 1.7 2000/05/30 16:27:04 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the code to implement ** the statement. Prior action routines should have already |
︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 | ** ** Space to hold the name is obtained from sqliteMalloc() and must ** be freed by the calling function. */ static char *sqliteTableNameFromToken(Token *pName){ char *zName = 0; sqliteSetNString(&zName, pName->z, pName->n, 0); return zName; } /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response ** to a CREATE TABLE statement. | > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | ** ** Space to hold the name is obtained from sqliteMalloc() and must ** be freed by the calling function. */ static char *sqliteTableNameFromToken(Token *pName){ char *zName = 0; sqliteSetNString(&zName, pName->z, pName->n, 0); sqliteDequote(zName); return zName; } /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response ** to a CREATE TABLE statement. |
︙ | ︙ | |||
248 249 250 251 252 253 254 255 256 257 258 259 260 261 | if( p->azCol==0 ){ p->nCol = 0; return; } pz = &p->azCol[p->nCol++]; *pz = 0; sqliteSetNString(pz, pName->z, pName->n, 0); } /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure is added to the internal hash tables. | > | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | if( p->azCol==0 ){ p->nCol = 0; return; } pz = &p->azCol[p->nCol++]; *pz = 0; sqliteSetNString(pz, pName->z, pName->n, 0); sqliteDequote(*pz); } /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure is added to the internal hash tables. |
︙ | ︙ | |||
661 662 663 664 665 666 667 668 669 670 671 672 673 674 | } } i = pList->nExpr++; pList->a[i].pExpr = pExpr; pList->a[i].zName = 0; if( pName ){ sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0); } return pList; } /* ** Delete an entire expression list. */ | > | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 | } } i = pList->nExpr++; pList->a[i].pExpr = pExpr; pList->a[i].zName = 0; if( pName ){ sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0); sqliteDequote(pList->a[i].zName); } return pList; } /* ** Delete an entire expression list. */ |
︙ | ︙ | |||
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 | pList->nId = 0; return pList; } } memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); if( pToken ){ sqliteSetNString(&pList->a[pList->nId].zName, pToken->z, pToken->n, 0); } pList->nId++; return pList; } /* ** Add an alias to the last identifier on the given identifier list. */ void sqliteIdListAddAlias(IdList *pList, Token *pToken){ if( pList && pList->nId>0 ){ int i = pList->nId - 1; sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); } } /* ** Delete an entire IdList */ void sqliteIdListDelete(IdList *pList){ | > > | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | pList->nId = 0; return pList; } } memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); if( pToken ){ sqliteSetNString(&pList->a[pList->nId].zName, pToken->z, pToken->n, 0); sqliteDequote(pList->a[pList->nId].zName); } pList->nId++; return pList; } /* ** Add an alias to the last identifier on the given identifier list. */ void sqliteIdListAddAlias(IdList *pList, Token *pToken){ if( pList && pList->nId>0 ){ int i = pList->nId - 1; sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); sqliteDequote(pList->a[i].zAlias); } } /* ** Delete an entire IdList */ void sqliteIdListDelete(IdList *pList){ |
︙ | ︙ | |||
1429 1430 1431 1432 1433 1434 1435 | sqliteFree(apIdx); sqliteFree(aXRef); sqliteIdListDelete(pTabList); sqliteExprListDelete(pChanges); sqliteExprDelete(pWhere); return; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 | sqliteFree(apIdx); sqliteFree(aXRef); sqliteIdListDelete(pTabList); sqliteExprListDelete(pChanges); sqliteExprDelete(pWhere); return; } /* ** The COPY command is for compatibility with PostgreSQL and specificially ** for the ability to read the output of pg_dump. The format is as ** follows: ** ** COPY table FROM file [USING DELIMITERS string] ** ** "table" is an existing table name. We will read lines of code from ** file to fill this table with data. File might be "stdin". The optional ** delimiter string identifies the field separators. The default is a tab. */ void sqliteCopy( Parse *pParse, /* The parser context */ Token *pTableName, /* The name of the table into which we will insert */ Token *pFilename, /* The file from which to obtain information */ Token *pDelimiter /* Use this as the field delimiter */ ){ Table *pTab; char *zTab; int i, j; Vdbe *v; int addr, end; Index *pIdx; zTab = sqliteTableNameFromToken(pTableName); pTab = sqliteFindTable(pParse->db, zTab); sqliteFree(zTab); if( pTab==0 ){ sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, pTableName->z, pTableName->n, 0); pParse->nErr++; goto copy_cleanup; } if( pTab->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not be modified", 0); pParse->nErr++; goto copy_cleanup; } v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe); if( v ){ addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0); sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n); sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ sqliteVdbeAddOp(v, OP_Open, i, 0, pIdx->zName, 0); } end = sqliteVdbeMakeLabel(v); addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end, 0, 0); if( pDelimiter ){ sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n); sqliteVdbeDequoteP3(v, addr); }else{ sqliteVdbeChangeP3(v, addr, "\t", 1); } sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0); if( pTab->pIndex ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); } for(i=0; i<pTab->nCol; i++){ sqliteVdbeAddOp(v, OP_FileField, i, 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0); sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( pIdx->pNext ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); } for(j=0; j<pIdx->nField; j++){ sqliteVdbeAddOp(v, OP_FileField, pIdx->aiField[j], 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nField, 0, 0, 0); sqliteVdbeAddOp(v, OP_PutIdx, i, 0, 0, 0); } sqliteVdbeAddOp(v, OP_Goto, 0, addr, 0, 0); sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, end); } copy_cleanup: return; } |
Changes to src/parse.y.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.2 2000/05/30 16:27:04 drh Exp $ */ %token_prefix TK_ %token_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetNString(&pParse->zErrMsg,"syntax error near \"",0,TOKEN.z,TOKEN.n, "\"", 1, 0); |
︙ | ︙ | |||
61 62 63 64 65 66 67 | ecmd ::= cmd. {sqliteExec(pParse);} ecmd ::= . explain ::= EXPLAIN. {pParse->explain = 1;} // The first form of a command is a CREATE TABLE statement. // cmd ::= create_table create_table_args. | | | > > > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | ecmd ::= cmd. {sqliteExec(pParse);} ecmd ::= . explain ::= EXPLAIN. {pParse->explain = 1;} // The first form of a command is a CREATE TABLE statement. // cmd ::= create_table create_table_args. create_table ::= CREATE(X) TABLE id(Y). {sqliteStartTable(pParse,&X,&Y);} create_table_args ::= LP columnlist conslist_opt RP(X). {sqliteEndTable(pParse,&X);} columnlist ::= columnlist COMMA column. columnlist ::= column. // About the only information used for a column is the name of the // column. The type is always just "text". But the code will accept // an elaborate typename. Perhaps someday we'll do something with it. // column ::= columnid type carglist. columnid ::= id(X). {sqliteAddColumn(pParse,&X);} %type id {Token} id(A) ::= ID(X). {A = X;} id(A) ::= STRING(X). {A = X;} type ::= typename. type ::= typename LP signed RP. type ::= typename LP signed COMMA signed RP. typename ::= ID. typename ::= typename ID. signed ::= INTEGER. signed ::= PLUS INTEGER. |
︙ | ︙ | |||
108 109 110 111 112 113 114 | conslist ::= tcons. tcons ::= CONSTRAINT ID tcons2. tcons ::= tcons2. tcons2 ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,0,0);} tcons2 ::= UNIQUE LP idlist RP. tcons2 ::= CHECK expr. | | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | conslist ::= tcons. tcons ::= CONSTRAINT ID tcons2. tcons ::= tcons2. tcons2 ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,0,0);} tcons2 ::= UNIQUE LP idlist RP. tcons2 ::= CHECK expr. idlist ::= idlist COMMA id. idlist ::= id. // The next command format is dropping tables. // cmd ::= DROP TABLE id(X). {sqliteDropTable(pParse,&X);} // The select statement // cmd ::= select. select ::= SELECT selcollist(W) from(X) where_opt(Y) orderby_opt(Z). {sqliteSelect(pParse, W, X, Y, Z);} select ::= SELECT STAR from(X) where_opt(Y) orderby_opt(Z). |
︙ | ︙ | |||
145 146 147 148 149 150 151 | %destructor stl_prefix {sqliteIdListDelete($$);} %type from {IdList*} %destructor from {sqliteIdListDelete($$);} from(A) ::= FROM seltablist(X). {A = X;} stl_prefix(A) ::= seltablist(X) COMMA. {A = X;} stl_prefix(A) ::= . {A = 0;} | | | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | %destructor stl_prefix {sqliteIdListDelete($$);} %type from {IdList*} %destructor from {sqliteIdListDelete($$);} from(A) ::= FROM seltablist(X). {A = X;} stl_prefix(A) ::= seltablist(X) COMMA. {A = X;} stl_prefix(A) ::= . {A = 0;} seltablist(A) ::= stl_prefix(X) id(Y). {A = sqliteIdListAppend(X,&Y);} seltablist(A) ::= stl_prefix(X) id(Y) AS id(Z). {A = sqliteIdListAppend(X,&Y); sqliteIdListAddAlias(A,&Z);} %type orderby_opt {ExprList*} %destructor orderby_opt {sqliteExprListDelete($$);} %type sortlist {ExprList*} %destructor sortlist {sqliteExprListDelete($$);} |
︙ | ︙ | |||
296 297 298 299 300 301 302 | idxlist(A) ::= idxlist(X) COMMA idxitem(Y). {A = sqliteIdListAppend(X,&Y);} idxlist(A) ::= idxitem(Y). {A = sqliteIdListAppend(0,&Y);} idxitem(A) ::= ID(X). {A = X;} | | > > > > > | 299 300 301 302 303 304 305 306 307 308 309 310 311 | idxlist(A) ::= idxlist(X) COMMA idxitem(Y). {A = sqliteIdListAppend(X,&Y);} idxlist(A) ::= idxitem(Y). {A = sqliteIdListAppend(0,&Y);} idxitem(A) ::= ID(X). {A = X;} cmd ::= DROP INDEX id(X). {sqliteDropIndex(pParse, &X);} cmd ::= COPY id(X) FROM id(Y) USING DELIMITERS STRING(Z). {sqliteCopy(pParse,&X,&Y,&Z);} cmd ::= COPY id(X) FROM id(Y). {sqliteCopy(pParse,&X,&Y,0);} |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.3 2000/05/30 16:27:04 drh Exp $ */ #include "sqlite.h" #include "dbbe.h" #include "vdbe.h" #include "parse.h" #include <gdbm.h> #include <stdio.h> |
︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 | void *sqliteMalloc(int); void sqliteFree(void*); void *sqliteRealloc(void*,int); #endif int sqliteGetToken(const char*, int *); void sqliteSetString(char **, const char *, ...); void sqliteSetNString(char **, ...); int sqliteRunParser(Parse*, char*, char **); void sqliteExec(Parse*); Expr *sqliteExpr(int, Expr*, Expr*, Token*); Expr *sqliteExprFunction(ExprList*, Token*); void sqliteExprDelete(Expr*); ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*); void sqliteExprListDelete(ExprList*); | > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | void *sqliteMalloc(int); void sqliteFree(void*); void *sqliteRealloc(void*,int); #endif int sqliteGetToken(const char*, int *); void sqliteSetString(char **, const char *, ...); void sqliteSetNString(char **, ...); void sqliteDequote(char*); int sqliteRunParser(Parse*, char*, char **); void sqliteExec(Parse*); Expr *sqliteExpr(int, Expr*, Expr*, Token*); Expr *sqliteExprFunction(ExprList*, Token*); void sqliteExprDelete(Expr*); ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*); void sqliteExprListDelete(ExprList*); |
︙ | ︙ | |||
242 243 244 245 246 247 248 | void sqliteUpdate(Parse*, Token*, ExprList*, Expr*); WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int); void sqliteWhereEnd(WhereInfo*); void sqliteExprCode(Parse*, Expr*); void sqliteExprIfTrue(Parse*, Expr*, int); void sqliteExprIfFalse(Parse*, Expr*, int); Table *sqliteFindTable(sqlite*,char*); | > | 243 244 245 246 247 248 249 250 | void sqliteUpdate(Parse*, Token*, ExprList*, Expr*); WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int); void sqliteWhereEnd(WhereInfo*); void sqliteExprCode(Parse*, Expr*); void sqliteExprIfTrue(Parse*, Expr*, int); void sqliteExprIfFalse(Parse*, Expr*, int); Table *sqliteFindTable(sqlite*,char*); void sqliteCopy(Parse*, Token*, Token*, Token*); |
Changes to src/tokenize.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.3 2000/05/30 16:27:04 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <stdlib.h> /* ** All the keywords of the SQL language are stored as in a hash |
︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | static Keyword aKeywordTable[] = { { "AND", 0, TK_AND, 0 }, { "AS", 0, TK_AS, 0 }, { "ASC", 0, TK_ASC, 0 }, { "BY", 0, TK_BY, 0 }, { "CHECK", 0, TK_CHECK, 0 }, { "CONSTRAINT", 0, TK_CONSTRAINT, 0 }, { "CREATE", 0, TK_CREATE, 0 }, { "DEFAULT", 0, TK_DEFAULT, 0 }, { "DELETE", 0, TK_DELETE, 0 }, { "DESC", 0, TK_DESC, 0 }, { "DROP", 0, TK_DROP, 0 }, { "EXPLAIN", 0, TK_EXPLAIN, 0 }, { "FROM", 0, TK_FROM, 0 }, { "INDEX", 0, TK_INDEX, 0 }, { "INSERT", 0, TK_INSERT, 0 }, { "INTO", 0, TK_INTO, 0 }, | > > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | static Keyword aKeywordTable[] = { { "AND", 0, TK_AND, 0 }, { "AS", 0, TK_AS, 0 }, { "ASC", 0, TK_ASC, 0 }, { "BY", 0, TK_BY, 0 }, { "CHECK", 0, TK_CHECK, 0 }, { "CONSTRAINT", 0, TK_CONSTRAINT, 0 }, { "COPY", 0, TK_COPY, 0 }, { "CREATE", 0, TK_CREATE, 0 }, { "DEFAULT", 0, TK_DEFAULT, 0 }, { "DELETE", 0, TK_DELETE, 0 }, { "DELIMITERS", 0, TK_DELIMITERS, 0 }, { "DESC", 0, TK_DESC, 0 }, { "DROP", 0, TK_DROP, 0 }, { "EXPLAIN", 0, TK_EXPLAIN, 0 }, { "FROM", 0, TK_FROM, 0 }, { "INDEX", 0, TK_INDEX, 0 }, { "INSERT", 0, TK_INSERT, 0 }, { "INTO", 0, TK_INTO, 0 }, |
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | { "ORDER", 0, TK_ORDER, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, { "SELECT", 0, TK_SELECT, 0 }, { "SET", 0, TK_SET, 0 }, { "TABLE", 0, TK_TABLE, 0 }, { "UNIQUE", 0, TK_UNIQUE, 0 }, { "UPDATE", 0, TK_UPDATE, 0 }, { "VALUES", 0, TK_VALUES, 0 }, { "WHERE", 0, TK_WHERE, 0 }, }; /* ** This is the hash table */ | > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | { "ORDER", 0, TK_ORDER, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, { "SELECT", 0, TK_SELECT, 0 }, { "SET", 0, TK_SET, 0 }, { "TABLE", 0, TK_TABLE, 0 }, { "UNIQUE", 0, TK_UNIQUE, 0 }, { "UPDATE", 0, TK_UPDATE, 0 }, { "USING", 0, TK_USING, 0 }, { "VALUES", 0, TK_VALUES, 0 }, { "WHERE", 0, TK_WHERE, 0 }, }; /* ** This is the hash table */ |
︙ | ︙ | |||
284 285 286 287 288 289 290 | static FILE *trace = 0; extern void *sqliteParserAlloc(void*(*)(int)); extern void sqliteParserFree(void*, void(*)(void*)); extern int sqliteParser(void*, int, ...); extern void sqliteParserTrace(FILE*, char *); i = 0; | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | static FILE *trace = 0; extern void *sqliteParserAlloc(void*(*)(int)); extern void sqliteParserFree(void*, void(*)(void*)); extern int sqliteParser(void*, int, ...); extern void sqliteParserTrace(FILE*, char *); i = 0; pEngine = sqliteParserAlloc((void*(*)(int))malloc); if( pEngine==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); return 1; } sqliteParserTrace(trace, "parser: "); while( nErr==0 && i>=0 && zSql[i]!=0 ){ int tokenType; |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.6 2000/05/30 16:27:04 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> #ifdef MEMORY_DEBUG |
︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 | if( n<=0 ) n = strlen(z); strncpy(zResult, z, n); zResult += n; } *zResult = 0; va_end(ap); } /* An array to map all upper-case characters into their corresponding ** lower-case character. */ static unsigned char UpperToLower[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, | > > > > > > > > > > > > > > > > > > > > > > > > > > | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | if( n<=0 ) n = strlen(z); strncpy(zResult, z, n); zResult += n; } *zResult = 0; va_end(ap); } /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine ** is a no-op. */ void sqliteDequote(char *z){ int quote; int i, j; quote = z[0]; if( quote!='\'' && quote!='"' ) return; for(i=1, j=0; z[i]; i++){ if( z[i]==quote ){ if( z[i+1]==quote ){ z[j++] = quote; i++; }else{ z[j++] = 0; break; } }else{ z[j++] = z[i]; } } } /* An array to map all upper-case characters into their corresponding ** lower-case character. */ static unsigned char UpperToLower[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.2 2000/05/30 16:27:04 drh Exp $ */ #include "sqliteInt.h" /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. |
︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 | char **azColName; /* Becomes the 4th parameter to callbacks */ int nTable; /* Number of slots in aTab[] */ VdbeTable *aTab; /* On element of this array for each open table */ int nList; /* Number of slots in apList[] */ FILE **apList; /* An open file for each list */ int nSort; /* Number of slots in apSort[] */ Sorter **apSort; /* An open sorter list */ }; /* ** Create a new virtual database engine. */ Vdbe *sqliteVdbeCreate(Dbbe *pBe){ Vdbe *p; | > > > > > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | char **azColName; /* Becomes the 4th parameter to callbacks */ int nTable; /* Number of slots in aTab[] */ VdbeTable *aTab; /* On element of this array for each open table */ int nList; /* Number of slots in apList[] */ FILE **apList; /* An open file for each list */ int nSort; /* Number of slots in apSort[] */ Sorter **apSort; /* An open sorter list */ FILE *pFile; /* At most one open file handler */ int nField; /* Number of file fields */ char **azField; /* Data for each file field */ char *zLine; /* A single line from the input file */ int nLineAlloc; /* Number of spaces allocated for zLine */ }; /* ** Create a new virtual database engine. */ Vdbe *sqliteVdbeCreate(Dbbe *pBe){ Vdbe *p; |
︙ | ︙ | |||
247 248 249 250 251 252 253 | ** the quotes. ** ** The quoting operator can be either a grave ascent (ASCII 0x27) ** or a double quote character (ASCII 0x22). Two quotes in a row ** resolve to be a single actual quote character within the string. */ void sqliteVdbeDequoteP3(Vdbe *p, int addr){ | < < | < < < < < < < < < < < < < < | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | ** the quotes. ** ** The quoting operator can be either a grave ascent (ASCII 0x27) ** or a double quote character (ASCII 0x22). Two quotes in a row ** resolve to be a single actual quote character within the string. */ void sqliteVdbeDequoteP3(Vdbe *p, int addr){ char *z; if( addr<0 || addr>=p->nOp ) return; z = p->aOp[addr].p3; sqliteDequote(z); } /* ** Create a new symbolic label for an instruction that has yet to be ** coded. The symbolic label is really just a negative number. The ** label can be used as the P2 value of an operation. Later, when ** the label is resolved to a specific address, the VDBE will scan |
︙ | ︙ | |||
351 352 353 354 355 356 357 358 359 360 361 362 363 364 | sqliteFree(pSorter->pData); sqliteFree(pSorter); } } sqliteFree(p->apSort); p->apSort = 0; p->nSort = 0; } /* ** Delete an entire VDBE. */ void sqliteVdbeDelete(Vdbe *p){ int i; | > > > > > > > > > > > > > > | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | sqliteFree(pSorter->pData); sqliteFree(pSorter); } } sqliteFree(p->apSort); p->apSort = 0; p->nSort = 0; if( p->pFile ){ if( p->pFile!=stdin ) fclose(p->pFile); p->pFile = 0; } if( p->azField ){ sqliteFree(p->azField); p->azField = 0; } p->nField = 0; if( p->zLine ){ sqliteFree(p->zLine); p->zLine = 0; } p->nLineAlloc = 0; } /* ** Delete an entire VDBE. */ void sqliteVdbeDelete(Vdbe *p){ int i; |
︙ | ︙ | |||
391 392 393 394 395 396 397 | "Open", "Close", "Destroy", "Fetch", "New", "Put", "Delete", "Field", "Key", "Rewind", "Next", "ResetIdx", "NextIdx", "PutIdx", "DeleteIdx", "ListOpen", "ListWrite", "ListRewind", "ListRead", "ListClose", "SortOpen", "SortPut", "SortMakeRec", "SortMakeKey", "Sort", "SortNext", "SortKey", "SortCallback", | > | | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | "Open", "Close", "Destroy", "Fetch", "New", "Put", "Delete", "Field", "Key", "Rewind", "Next", "ResetIdx", "NextIdx", "PutIdx", "DeleteIdx", "ListOpen", "ListWrite", "ListRewind", "ListRead", "ListClose", "SortOpen", "SortPut", "SortMakeRec", "SortMakeKey", "Sort", "SortNext", "SortKey", "SortCallback", "SortClose", "FileOpen", "FileRead", "FileField", "FileClose", "MakeRecord", "MakeKey", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "Integer", "String", "Pop", "Dup", "Pull", "Add", "AddImm", "Subtract", "Multiply", "Divide", "Min", "Max", "Eq", "Ne", "Lt", "Le", "Gt", "Ge", "IsNull", "NotNull", "Negative", "And", "Or", |
︙ | ︙ | |||
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 | sqliteFree(pSorter->zKey); sqliteFree(pSorter->pData); sqliteFree(pSorter); } } break; } /* An other opcode is illegal... */ default: { sprintf(zBuf,"%d",pOp->opcode); sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0); rc = 1; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | sqliteFree(pSorter->zKey); sqliteFree(pSorter->pData); sqliteFree(pSorter); } } break; } /* Opcode: FileOpen * * P3 ** ** Open the file named by P3 for reading using the FileRead opcode. ** If P3 is "stdin" then output standard input for reading. */ case OP_FileOpen: { if( pOp->p3==0 ) goto bad_instruction; if( p->pFile ){ if( p->pFile!=stdin ) fclose(p->pFile); p->pFile = 0; } if( sqliteStrICmp(pOp->p3,"stdin")==0 ){ p->pFile = stdin; }else{ p->pFile = fopen(pOp->p3, "r"); } if( p->pFile==0 ){ sqliteSetString(pzErrMsg,"unable to open file: ", pOp->p3, 0); rc = 1; goto cleanup; } break; } /* Opcode: FileClose * * * ** ** Close a file previously opened using FileOpen. This is a no-op ** if there is no prior FileOpen call. */ case OP_FileClose: { if( p->pFile ){ if( p->pFile!=stdin ) fclose(p->pFile); p->pFile = 0; } if( p->azField ){ sqliteFree(p->azField); p->azField = 0; } p->nField = 0; if( p->zLine ){ sqliteFree(p->zLine); p->zLine = 0; } p->nLineAlloc = 0; break; } /* Opcode: FileRead P1 P2 P3 ** ** Read a single line of input the open file (the file opened using ** FileOpen). If we reach end-of-file, jump immediately to P2. If ** we are able to get another line, split the line apart using P3 as ** a delimiter. There should be exactly P1 fields. Throw an exception ** if the number of fields is different from P1. */ case OP_FileRead: { int n, eol, nField, i, c, nDelim; char *zDelim, *z; if( p->pFile==0 ) goto fileread_jump; nField = pOp->p1; if( nField<=0 ) goto fileread_jump; if( nField!=p->nField || p->azField==0 ){ p->azField = sqliteRealloc(p->azField, sizeof(char*)*nField+1); if( p->azField==0 ){ p->nField = 0; goto fileread_jump; } p->nField = nField; } n = 0; eol = 0; while( eol==0 ){ if( p->zLine==0 || n+200>p->nLineAlloc ){ p->nLineAlloc = p->nLineAlloc*2 + 300; p->zLine = sqliteRealloc(p->zLine, p->nLineAlloc); if( p->zLine==0 ){ p->nLineAlloc = 0; goto fileread_jump; } } if( fgets(&p->zLine[n], p->nLineAlloc-n, p->pFile)==0 ){ eol = 1; p->zLine[n] = 0; }else{ while( p->zLine[n] ){ n++; } if( n>0 && p->zLine[n-1]=='\n' ){ n--; p->zLine[n] = 0; eol = 1; } } } if( n==0 ) goto fileread_jump; z = p->zLine; if( z[0]=='\\' && z[1]=='.' && z[2]==0 ){ goto fileread_jump; } zDelim = pOp->p3; if( zDelim==0 ) zDelim = "\t"; c = zDelim[0]; nDelim = strlen(zDelim); p->azField[0] = z; for(i=1; *z!=0 && i<nField; i++){ while( *z && (*z!=c || strncmp(z,zDelim,nDelim)) ){ z++; } if( *z ){ *z = 0; z += nDelim; p->azField[i] = z; } } while( i<nField ){ p->azField[i++] = ""; } break; /* If we reach end-of-file, or if anything goes wrong, jump here. ** This code will cause a jump to P2 */ fileread_jump: pc = pOp->p2; if( pc<0 || pc>p->nOp ){ sqliteSetString(pzErrMsg, "jump destination out of range", 0); rc = 1; } pc--; break; } /* Opcode: FileField P1 * * ** ** Push onto the stack the P1-th field of the most recently read line ** from the file. */ case OP_FileField: { int i = pOp->p1; char *z; if( NeedStack(p, p->tos+1) ) goto no_mem; if( i>=0 && i<p->nField && p->azField ){ z = p->azField[i]; }else{ z = 0; } if( z==0 ) z = ""; p->tos++; p->iStack[p->tos] = strlen(z) + 1; sqliteSetString(&p->zStack[p->tos], z, 0); break; } /* An other opcode is illegal... */ default: { sprintf(zBuf,"%d",pOp->opcode); sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0); rc = 1; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
23 24 25 26 27 28 29 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** 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.2 2000/05/30 16:27:05 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
99 100 101 102 103 104 105 | #define OP_SortMakeKey 24 #define OP_Sort 25 #define OP_SortNext 26 #define OP_SortKey 27 #define OP_SortCallback 28 #define OP_SortClose 29 | > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #define OP_SortMakeKey 24 #define OP_Sort 25 #define OP_SortNext 26 #define OP_SortKey 27 #define OP_SortCallback 28 #define OP_SortClose 29 #define OP_FileOpen 30 #define OP_FileRead 31 #define OP_FileField 32 #define OP_FileClose 33 #define OP_MakeRecord 34 #define OP_MakeKey 35 #define OP_Goto 36 #define OP_If 37 #define OP_Halt 38 #define OP_ColumnCount 39 #define OP_ColumnName 40 #define OP_Callback 41 #define OP_Integer 42 #define OP_String 43 #define OP_Pop 44 #define OP_Dup 45 #define OP_Pull 46 #define OP_Add 47 #define OP_AddImm 48 #define OP_Subtract 49 #define OP_Multiply 50 #define OP_Divide 51 #define OP_Min 52 #define OP_Max 53 #define OP_Eq 54 #define OP_Ne 55 #define OP_Lt 56 #define OP_Le 57 #define OP_Gt 58 #define OP_Ge 59 #define OP_IsNull 60 #define OP_NotNull 61 #define OP_Negative 62 #define OP_And 63 #define OP_Or 64 #define OP_Not 65 #define OP_Concat 66 #define OP_Noop 67 #define OP_MAX 67 /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ Vdbe *sqliteVdbeCreate(Dbbe*); int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int); |
︙ | ︙ |
Changes to test/table.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # # $Id: table.test,v 1.4 2000/05/30 16:27:05 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a basic table and verify it is added to sqlite_master # do_test table-1.1 { |
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | # still gone. # do_test table-1.6 { db close sqlite db testdb execsql {SELECT name FROM sqlite_master} } {} # Verify that we cannot make two tables with the same name # do_test table-2.1 { execsql {CREATE TABLE test2(one text)} set v [catch {execsql {CREATE TABLE test2(two text)}} msg] | > > > > > > > > > > > > > > > > > > > > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | # still gone. # do_test table-1.6 { db close sqlite db testdb execsql {SELECT name FROM sqlite_master} } {} # Repeat the above steps, but this time quote the table name. # do_test table-1.10 { execsql {CREATE TABLE "create" (f1 int)} execsql {SELECT name FROM sqlite_master} } {create} do_test table-1.11 { execsql {DROP TABLE "create"} execsql {SELECT name FROM "sqlite_master"} } {} do_test table-1.12 { execsql {CREATE TABLE test1("f1 ho" int)} execsql {SELECT name as "X" FROM sqlite_master} } {test1} do_test table-1.13 { execsql {DROP TABLE "TEST1"} execsql {SELECT name FROM "sqlite_master"} } {} # Verify that we cannot make two tables with the same name # do_test table-2.1 { execsql {CREATE TABLE test2(one text)} set v [catch {execsql {CREATE TABLE test2(two text)}} msg] |
︙ | ︙ |