Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Changes to the DBBE. Moving toward having many more backend driver choices. (CVS 176) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c0730217a04323a1a73d125e3e7da32b |
User & Date: | drh 2001-01-13 14:34:06.000 |
Context
2001-01-15
| ||
22:51 | continued progress toward version 2.0 (CVS 177) (check-in: c6ffb7ec6a user: drh tags: trunk) | |
2001-01-13
| ||
14:34 | Changes to the DBBE. Moving toward having many more backend driver choices. (CVS 176) (check-in: c0730217a0 user: drh tags: trunk) | |
2001-01-04
| ||
14:30 | Version 1.0.18 (CVS 485) (check-in: 46b86abb1c user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
44 45 46 47 48 49 50 | # The library that programs using readline() must link against. # LIBREADLINE = @TARGET_READLINE_LIBS@ # Object files for the SQLite library. # LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \ | | | > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | # The library that programs using readline() must link against. # LIBREADLINE = @TARGET_READLINE_LIBS@ # Object files for the SQLite library. # LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \ main.o parse.o printf.o random.o select.o table.o tokenize.o \ update.o util.o vdbe.o where.o tclsqlite.o # All of the source code files. # SRC = \ $(TOP)/src/build.c \ $(TOP)/src/dbbe.c \ $(TOP)/src/dbbegdbm.c \ $(TOP)/src/dbbemem.c \ $(TOP)/src/dbbe.h \ $(TOP)/src/dbbemem.c \ $(TOP)/src/delete.c \ $(TOP)/src/expr.c \ $(TOP)/src/insert.c \ $(TOP)/src/main.c \ $(TOP)/src/parse.y \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ $(TOP)/src/select.c \ $(TOP)/src/shell.c \ $(TOP)/src/sqlite.h.in \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/table.c \ $(TOP)/src/tclsqlite.c \ $(TOP)/src/tokenize.c \ |
︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | expr.o: $(TOP)/src/expr.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/expr.c insert.o: $(TOP)/src/insert.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/insert.c select.o: $(TOP)/src/select.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/select.c table.o: $(TOP)/src/table.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/table.c update.o: $(TOP)/src/update.c $(HDR) | > > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | expr.o: $(TOP)/src/expr.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/expr.c insert.o: $(TOP)/src/insert.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/insert.c random.o: $(TOP)/src/random.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/random.c select.o: $(TOP)/src/select.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/select.c table.o: $(TOP)/src/table.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/table.c update.o: $(TOP)/src/update.c $(HDR) |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 1.1.0 |
Changes to src/dbbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** ** $Id: dbbe.c,v 1.22 2001/01/13 14:34:06 drh Exp $ */ #include "sqliteInt.h" /* ** This routine opens a new database. It looks at the first ** few characters of the database name to try to determine what ** kind of database to open. If the first characters are "gdbm:", |
︙ | ︙ | |||
58 59 60 61 62 63 64 | } if( strncmp(zName, "memory:", 7)==0 ){ extern Dbbe *sqliteMemOpen(const char*,int,int,char**); return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg); } return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 58 59 60 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 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 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 | } if( strncmp(zName, "memory:", 7)==0 ){ extern Dbbe *sqliteMemOpen(const char*,int,int,char**); return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg); } return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg); } /* ** Open a temporary file. The file should be deleted when closed. ** ** Note that we can't use the old Unix trick of opening the file ** and then immediately unlinking the file. That works great ** under Unix, but fails when we try to port to Windows. */ int sqliteDbbeOpenTempFile(Dbbe *pBe, FILE **ppFile){ char *zFile; /* Full name of the temporary file */ char zBuf[50]; /* Base name of the temporary file */ int i; /* Loop counter */ int limit; /* Prevent an infinite loop */ int rc = SQLITE_OK; /* Value returned by this function */ char *zDir; /* Directory to hold the file */ for(i=0; i<pBe->nTemp; i++){ if( pBe->apTemp[i]==0 ) break; } if( i>=pBe->nTemp ){ pBe->nTemp++; pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) ); pBe->azTemp = sqliteRealloc(pBe->azTemp, pBe->nTemp*sizeof(char*) ); } if( pBe->apTemp==0 ){ *ppFile = 0; return SQLITE_NOMEM; } limit = 4; zFile = 0; zDir = pBe->zDir; if( zDir==0 ){ zDir = "./"; } do{ sqliteRandomName(zBuf, "/_temp_file_"); sqliteFree(zFile); zFile = 0; sqliteSetString(&zFile, zDir, zBuf, 0); }while( access(zFile,0)==0 && limit-- >= 0 ); *ppFile = pBe->apTemp[i] = fopen(zFile, "w+"); if( pBe->apTemp[i]==0 ){ rc = SQLITE_ERROR; sqliteFree(zFile); pBe->azTemp[i] = 0; }else{ pBe->azTemp[i] = zFile; } return rc; } /* ** Close a temporary file opened using sqliteGdbmOpenTempFile() */ void sqliteDbbeCloseTempFile(Dbbe *pBe, FILE *f){ int i; for(i=0; i<pBe->nTemp; i++){ if( pBe->apTemp[i]==f ){ unlink(pBe->azTemp[i]); sqliteFree(pBe->azTemp[i]); pBe->apTemp[i] = 0; pBe->azTemp[i] = 0; break; } } fclose(f); } /* ** Close all temporary files that happen to still be open. ** This routine is called when the database is being closed. */ void sqliteDbbeCloseAllTempFiles(Dbbe *pBe){ int i; for(i=0; i<pBe->nTemp; i++){ if( pBe->apTemp[i]!=0 ){ unlink(pBe->azTemp[i]); fclose(pBe->apTemp[i]); sqliteFree(pBe->azTemp[i]); pBe->apTemp[i] = 0; pBe->azTemp[i] = 0; break; } } sqliteFree(pBe->azTemp); sqliteFree(pBe->apTemp); } |
Changes to src/dbbe.h.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** This file defines the interface to the database backend (Dbbe). ** ** The database backend is designed to be as general as possible ** so that it can easily be replaced by a different backend. ** This library was originally designed to support the following ** backends: GDBM, NDBM, SDBM, Berkeley DB. ** | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** This file defines the interface to the database backend (Dbbe). ** ** The database backend is designed to be as general as possible ** so that it can easily be replaced by a different backend. ** This library was originally designed to support the following ** backends: GDBM, NDBM, SDBM, Berkeley DB. ** ** $Id: dbbe.h,v 1.9 2001/01/13 14:34:06 drh Exp $ */ #ifndef _SQLITE_DBBE_H_ #define _SQLITE_DBBE_H_ #include <stdio.h> /* ** The database backend supports two opaque structures. A Dbbe is |
︙ | ︙ | |||
49 50 51 52 53 54 55 | ** The DbbeCursor structure holds some state information, such as ** the key and data from the last retrieval. For this reason, ** the backend must allow the creation of multiple independent ** DbbeCursor structures for each table in the database. */ typedef struct Dbbe Dbbe; typedef struct DbbeCursor DbbeCursor; | | | | > > > | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | ** The DbbeCursor structure holds some state information, such as ** the key and data from the last retrieval. For this reason, ** the backend must allow the creation of multiple independent ** DbbeCursor structures for each table in the database. */ typedef struct Dbbe Dbbe; typedef struct DbbeCursor DbbeCursor; typedef struct DbbeMethods DbbeMethods; /* ** Open a complete database. ** ** If the database name begins with "gdbm:" the GDBM driver is used. ** If the name begins with "memory:" the in-memory driver is used. ** The default driver is GDBM. */ Dbbe *sqliteDbbeOpen(const char *zName, int write, int create, char **pzErr); /* ** Each of the various SQLite backends defines a set of methods for ** accessing the database. Pointers to the methods are contained in ** an instance of the following structure. A pointer to a static instance ** of this structure is assigned to the Dbbe structure that sqlileDbbeOpen ** returns. */ struct DbbeMethods { /* Close the whole database. */ void (*Close)(Dbbe*); /* Open a cursor into particular file of a previously opened database. ** Create the file if it doesn't already exist and writeable!=0. zName ** is the base name of the file to be opened. This routine will add ** an appropriate path and extension to the filename to locate the |
︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 | /* Open a file suitable for temporary storage */ int (*OpenTempFile)(Dbbe*, FILE**); /* Close a temporary file */ void (*CloseTempFile)(Dbbe *, FILE *); }; #endif /* defined(_SQLITE_DBBE_H_) */ | > > > > > > > > > > > > > > > > > > | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | /* Open a file suitable for temporary storage */ int (*OpenTempFile)(Dbbe*, FILE**); /* Close a temporary file */ void (*CloseTempFile)(Dbbe *, FILE *); }; /* ** This is the structure returned by sqliteDbbeOpen(). It contains ** information common to all the different backend drivers. ** ** The information in this structure (with the exception the method ** pointers in the Dbbe.x field) is intended to be visible to ** the backend drivers only. Users should not access or modify ** this structure in any way other than the read the method pointers ** in Dbbe.x. */ struct Dbbe { struct DbbeMethods *x; /* Backend-specific methods for database access */ char *zDir; /* The directory containing the database file(s) */ int nTemp; /* Number of temporary files created */ FILE **apTemp; /* Space to hold temporary file pointers */ char **azTemp; /* Names of the temporary files */ }; #endif /* defined(_SQLITE_DBBE_H_) */ |
Changes to src/dbbegdbm.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses GDBM as the database backend. It should be ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** ** $Id: dbbegdbm.c,v 1.2 2001/01/13 14:34:06 drh Exp $ */ #include "sqliteInt.h" #include <gdbm.h> #include <sys/stat.h> #include <unistd.h> #include <ctype.h> #include <time.h> |
︙ | ︙ | |||
53 54 55 56 57 58 59 | GDBM_FILE dbf; /* The file itself */ int nRef; /* Number of references */ int delOnClose; /* Delete when closing */ int writeable; /* Opened for writing */ BeFile *pNext, *pPrev; /* Next and previous on list of open files */ }; | < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < | | < < < < < < < > | < | 53 54 55 56 57 58 59 60 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 90 91 92 93 94 95 96 97 98 99 100 101 | GDBM_FILE dbf; /* The file itself */ int nRef; /* Number of references */ int delOnClose; /* Delete when closing */ int writeable; /* Opened for writing */ BeFile *pNext, *pPrev; /* Next and previous on list of open files */ }; /* ** The following structure contains all information used by GDBM ** database driver. This is a subclass of the Dbbe structure. */ typedef struct Dbbex Dbbex; struct Dbbex { Dbbe dbbe; /* The base class */ int write; /* True for write permission */ BeFile *pOpen; /* List of open files */ }; /* ** An cursor into a database file is an instance of the following structure. ** There can only be a single BeFile structure for each disk file, but ** there can be multiple DbbeCursor structures. Each DbbeCursor represents ** a cursor pointing to a particular part of the open BeFile. The ** BeFile.nRef field hold a count of the number of DbbeCursor structures ** associated with the same disk file. */ struct DbbeCursor { Dbbex *pBe; /* The database of which this record is a part */ BeFile *pFile; /* The database file for this table */ datum key; /* Most recently used key */ datum data; /* Most recent data */ int needRewind; /* Next key should be the first */ int readPending; /* The fetch hasn't actually been done yet */ }; /* ** */ struct DbbeList { FILE *pOut; Dbbe *pDbbe; }; /* ** The "mkdir()" function only takes one argument under Windows. */ #if OS_WIN # define mkdir(A,B) mkdir(A) #endif |
︙ | ︙ | |||
161 162 163 164 165 166 167 | int i; for(pFile=pBe->pOpen; pFile; pFile=pNext){ pNext = pFile->pNext; gdbm_close(pFile->dbf); memset(pFile, 0, sizeof(*pFile)); sqliteFree(pFile); } | < < < < < < < < < < | < | | < < < < < < < < < < < < < < < < < < < < < | 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 | int i; for(pFile=pBe->pOpen; pFile; pFile=pNext){ pNext = pFile->pNext; gdbm_close(pFile->dbf); memset(pFile, 0, sizeof(*pFile)); sqliteFree(pFile); } sqliteDbbeCloseAllTempFiles(pDbbe); memset(pBe, 0, sizeof(*pBe)); sqliteFree(pBe); } /* ** Translate the name of an SQL table (or index) into the name ** of a file that holds the key/data pairs for that table or ** index. Space to hold the filename is obtained from ** sqliteMalloc() and must be freed by the calling function. */ static char *sqliteFileOfTable(Dbbex *pBe, const char *zTable){ char *zFile = 0; int i; sqliteSetString(&zFile, pBe->dbbe.zDir, "/", zTable, ".tbl", 0); if( zFile==0 ) return 0; for(i=strlen(pBe->dbbe.zDir)+1; zFile[i]; i++){ int c = zFile[i]; if( isupper(c) ){ zFile[i] = tolower(c); }else if( !isalnum(c) && c!='-' && c!='_' && c!='.' ){ zFile[i] = '+'; } } return zFile; } /* ** Open a new table cursor. Write a pointer to the corresponding ** DbbeCursor structure into *ppCursr. Return an integer success ** code: ** ** SQLITE_OK It worked! ** |
︙ | ︙ | |||
291 292 293 294 295 296 297 | if( !writeable || pBe->write ){ pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0); }else{ pFile->dbf = 0; } }else{ int limit; | < < | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | if( !writeable || pBe->write ){ pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0); }else{ pFile->dbf = 0; } }else{ int limit; char zRandom[50]; zFile = 0; limit = 5; do { sqliteRandomName(zRandom, "_temp_table_"); sqliteFree(zFile); zFile = sqliteFileOfTable(pBe, zRandom); pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0); }while( pFile->dbf==0 && limit-- >= 0); pFile->delOnClose = 1; } pFile->writeable = writeable; |
︙ | ︙ | |||
573 574 575 576 577 578 579 | ** Get a new integer key. */ static int sqliteGdbmNew(DbbeCursor *pCursr){ int iKey; datum key; int go = 1; int i; | < < | < < < | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | ** Get a new integer key. */ static int sqliteGdbmNew(DbbeCursor *pCursr){ int iKey; datum key; int go = 1; int i; if( pCursr->pFile==0 || pCursr->pFile->dbf==0 ) return 1; while( go ){ iKey = sqliteRandomInteger(); if( iKey==0 ) continue; key.dptr = (char*)&iKey; key.dsize = 4; go = gdbm_exists(pCursr->pFile->dbf, key); } return iKey; } |
︙ | ︙ | |||
627 628 629 630 631 632 633 | key.dptr = pKey; rc = gdbm_delete(pCursr->pFile->dbf, key); if( rc ) rc = SQLITE_ERROR; return rc; } /* | | | < < < | < | | | < < | < < < < < | | < < < < < < < < < | > | | | | < < | < < < < < < | | | < | < < < < < | | < < < < | | | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | key.dptr = pKey; rc = gdbm_delete(pCursr->pFile->dbf, key); if( rc ) rc = SQLITE_ERROR; return rc; } /* ** This variable contains pointers to all of the access methods ** used to implement the GDBM backend. */ static struct DbbeMethods gdbmMethods = { /* n Close */ sqliteGdbmClose, /* OpenCursor */ sqliteGdbmOpenCursor, /* DropTable */ sqliteGdbmDropTable, /* ReorganizeTable */ sqliteGdbmReorganizeTable, /* CloseCursor */ sqliteGdbmCloseCursor, /* Fetch */ sqliteGdbmFetch, /* Test */ sqliteGdbmTest, /* CopyKey */ sqliteGdbmCopyKey, /* CopyData */ sqliteGdbmCopyData, /* ReadKey */ sqliteGdbmReadKey, /* ReadData */ sqliteGdbmReadData, /* KeyLength */ sqliteGdbmKeyLength, /* DataLength */ sqliteGdbmDataLength, /* NextKey */ sqliteGdbmNextKey, /* Rewind */ sqliteGdbmRewind, /* New */ sqliteGdbmNew, /* Put */ sqliteGdbmPut, /* Delete */ sqliteGdbmDelete, /* OpenTempFile */ sqliteDbbeOpenTempFile, /* CloseTempFile */ sqliteDbbeCloseTempFile }; /* ** This routine opens a new database. For the GDBM driver ** implemented here, the database name is the name of the directory ** containing all the files of the database. ** |
︙ | ︙ | |||
742 743 744 745 746 747 748 | } sqliteFree(zMaster); pNew = sqliteMalloc(sizeof(Dbbex) + strlen(zName) + 1); if( pNew==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); return 0; } | < < < < < < < < < < < < < < < | < < < < | | < < | 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | } sqliteFree(zMaster); pNew = sqliteMalloc(sizeof(Dbbex) + strlen(zName) + 1); if( pNew==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); return 0; } pNew->dbbe.x = &gdbmMethods; pNew->dbbe.zDir = (char*)&pNew[1]; strcpy(pNew->dbbe.zDir, zName); pNew->write = writeFlag; pNew->pOpen = 0; return &pNew->dbbe; } |
Changes to src/dbbemem.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** This file contains code to implement the database backend (DBBE) ** for sqlite. The database backend is the interface between ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses an in-memory hash table as the database backend. ** | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** This file contains code to implement the database backend (DBBE) ** for sqlite. The database backend is the interface between ** sqlite and the code that does the actually reading and writing ** of information to the disk. ** ** This file uses an in-memory hash table as the database backend. ** ** $Id: dbbemem.c,v 1.6 2001/01/13 14:34:06 drh Exp $ */ #include "sqliteInt.h" #include <sys/stat.h> #include <unistd.h> #include <ctype.h> #include <time.h> |
︙ | ︙ | |||
338 339 340 341 342 343 344 | typedef struct MTable MTable; struct MTable { char *zName; /* Name of the table */ int delOnClose; /* Delete when closing */ Array data; /* The data in this stable */ }; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 338 339 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 368 369 370 371 372 373 374 375 376 | typedef struct MTable MTable; struct MTable { char *zName; /* Name of the table */ int delOnClose; /* Delete when closing */ Array data; /* The data in this stable */ }; /* ** The following structure contains all information used by GDBM ** database driver. This is a subclass of the Dbbe structure. */ typedef struct Dbbex Dbbex; struct Dbbex { Dbbe dbbe; /* The base class */ Array tables; /* All tables of the database */ }; /* ** An cursor into a database file is an instance of the following structure. ** There can only be a single MTable structure for each disk file, but ** there can be multiple DbbeCursor structures. Each DbbeCursor represents ** a cursor pointing to a particular part of the open MTable. The ** MTable.nRef field hold a count of the number of DbbeCursor structures ** associated with the same disk file. */ struct DbbeCursor { Dbbex *pBe; /* The database of which this record is a part */ MTable *pTble; /* The database file for this table */ ArrayElem *elem; /* Most recently accessed record */ int needRewind; /* Next key should be the first */ }; /* ** Forward declaration */ static void sqliteMemCloseCursor(DbbeCursor *pCursr); /* ** Erase all the memory of an MTable |
︙ | ︙ | |||
449 450 451 452 453 454 455 | int i; ArrayElem *j, *k; for(j=ArrayFirst(&pBe->tables); j; j=ArrayNext(j)){ pTble = ArrayData(j); deleteMTable(pTble); } ArrayClear(&pBe->tables); | < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | int i; ArrayElem *j, *k; for(j=ArrayFirst(&pBe->tables); j; j=ArrayNext(j)){ pTble = ArrayData(j); deleteMTable(pTble); } ArrayClear(&pBe->tables); sqliteDbbeCloseAllTempFiles(pDbbe); memset(pBe, 0, sizeof(*pBe)); sqliteFree(pBe); } /* ** Translate the name of an SQL table (or index) into its ** canonical name. ** ** Space to hold the canonical name is obtained from ** sqliteMalloc() and must be freed by the calling function. */ |
︙ | ︙ | |||
748 749 750 751 752 753 754 | ** Get a new integer key. */ static int sqliteMemNew(DbbeCursor *pCursr){ int iKey; Datum key; int go = 1; int i; | < < | < < < | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | ** Get a new integer key. */ static int sqliteMemNew(DbbeCursor *pCursr){ int iKey; Datum key; int go = 1; int i; while( go ){ iKey = sqliteRandomInteger(); if( iKey==0 ) continue; key.p = (char*)&iKey; key.n = 4; go = ArrayFindElement(&pCursr->pTble->data, key)!=0; } return iKey; } |
︙ | ︙ | |||
800 801 802 803 804 805 806 | if( data.p ){ sqliteFree(data.p); } return SQLITE_OK; } /* | | | < < < > > | | > | | | < < | < < < < < < < < < < < < < < < < < | | | < < < | < < < < < < | | | | | < < < < < | | < < < < | | < < < < < < < < < < < < < < < < < | | < < < < < | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 | if( data.p ){ sqliteFree(data.p); } return SQLITE_OK; } /* ** This variable contains pointers to all of the access methods ** used to implement the MEMORY backend. */ static struct DbbeMethods memoryMethods = { /* n Close */ sqliteMemClose, /* OpenCursor */ sqliteMemOpenCursor, /* DropTable */ sqliteMemDropTable, /* ReorganizeTable */ sqliteMemReorganizeTable, /* CloseCursor */ sqliteMemCloseCursor, /* Fetch */ sqliteMemFetch, /* Test */ sqliteMemTest, /* CopyKey */ sqliteMemCopyKey, /* CopyData */ sqliteMemCopyData, /* ReadKey */ sqliteMemReadKey, /* ReadData */ sqliteMemReadData, /* KeyLength */ sqliteMemKeyLength, /* DataLength */ sqliteMemDataLength, /* NextKey */ sqliteMemNextKey, /* Rewind */ sqliteMemRewind, /* New */ sqliteMemNew, /* Put */ sqliteMemPut, /* Delete */ sqliteMemDelete, /* OpenTempFile */ sqliteDbbeOpenTempFile, /* CloseTempFile */ sqliteDbbeCloseTempFile }; /* ** This routine opens a new database. For the GDBM driver ** implemented here, the database name is the name of the directory ** containing all the files of the database. ** ** If successful, a pointer to the Dbbe structure is returned. ** If there are errors, an appropriate error message is left ** in *pzErrMsg and NULL is returned. */ Dbbe *sqliteMemOpen( const char *zName, /* The name of the database */ int writeFlag, /* True if we will be writing to the database */ int createFlag, /* True to create database if it doesn't exist */ char **pzErrMsg /* Write error messages (if any) here */ ){ Dbbex *pNew; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); return 0; } ArrayInit(&pNew->tables); pNew->dbbe.x = &memoryMethods; pNew->dbbe.zDir = 0; return &pNew->dbbe; } |
Changes to src/main.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.23 2001/01/13 14:34:06 drh Exp $ */ #include "sqliteInt.h" /* ** This is the callback routine for the code that initializes the ** database. Each callback contains text of a CREATE TABLE or ** CREATE INDEX statement that must be parsed to yield the internal |
︙ | ︙ | |||
235 236 237 238 239 240 241 | } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ int i; | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ int i; db->pBe->x->Close(db->pBe); for(i=0; i<N_HASH; i++){ Table *pNext, *pList = db->apTblHash[i]; db->apTblHash[i] = 0; while( pList ){ pNext = pList->pHash; pList->pHash = 0; sqliteDeleteTable(db, pList); |
︙ | ︙ |
Added src/random.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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 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 118 119 120 121 122 123 124 125 126 127 | /* ** Copyright (c) 2000 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public ** License as published by the Free Software Foundation; either ** version 2 of the License, or (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** ** $Id: random.c,v 1.1 2001/01/13 14:34:07 drh Exp $ */ #include "sqliteInt.h" /* ** Get a single 8-bit random value from the RC4 PRNG. */ int sqliteRandomByte(void){ int t; /* ** The following structure holds the current state of the RC4 algorithm. ** We use RC4 as a random number generator. Each call to RC4 gives ** a random 8-bit number. ** ** Nothing in this file or anywhere else in SQLite does any kind of ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random ** number generator) not as an encryption device. */ static struct { int isInit; int i, j; int s[256]; } prng_state; /* Initialize the state of the random number generator once, ** the first time this routine is called. The seed value does ** not need to contain a lot of randomness since we are not ** trying to do secure encryption or anything like that... */ if( !prng_state.isInit ){ int i; static char seed[] = " sqlite random seed"; char k[256]; time((time_t*)seed); prng_state.j = 0; prng_state.i = 0; for(i=0; i<256; i++){ prng_state.s[i] = i; k[i] = seed[i%sizeof(seed)]; } for(i=0; i<256; i++){ int t; prng_state.j = (prng_state.j + prng_state.s[i] + k[i]) & 0xff; t = prng_state.s[prng_state.j]; prng_state.s[prng_state.j] = prng_state.s[i]; prng_state.s[i] = t; } prng_state.isInit = 1; } /* Generate and return single random byte */ prng_state.i = (prng_state.i + 1) & 0xff; prng_state.j = (prng_state.j + prng_state.s[prng_state.i]) & 0xff; t = prng_state.s[prng_state.i]; prng_state.s[prng_state.i] = prng_state.s[prng_state.j]; prng_state.s[prng_state.j] = t; t = prng_state.s[prng_state.i] + prng_state.s[prng_state.j]; return t & 0xff; } /* ** Return a random 32-bit integer. The integer is generated by making ** 4 calls to sqliteRandomByte(). */ int sqliteRandomInteger(void){ int r; int i; r = sqliteRandomByte(); for(i=1; i<4; i++){ r = (r<<8) + sqliteRandomByte(); } return r; } /* ** Generate a random filename with the given prefix. The new filename ** is written into zBuf[]. The calling function must insure that ** zBuf[] is big enough to hold the prefix plus 20 or so extra ** characters. ** ** Very random names are chosen so that the chance of a ** collision with an existing filename is very very small. */ void sqliteRandomName(char *zBuf, char *zPrefix){ int i, j; static const char zRandomChars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; strcpy(zBuf, zPrefix); j = strlen(zBuf); for(i=0; i<15; i++){ int c = sqliteRandomByte() % (sizeof(zRandomChars) - 1); zBuf[j++] = zRandomChars[c]; } zBuf[j] = 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.34 2001/01/13 14:34:07 drh Exp $ */ #include "sqlite.h" #include "dbbe.h" #include "vdbe.h" #include "parse.h" #include <gdbm.h> #include <stdio.h> |
︙ | ︙ | |||
415 416 417 418 419 420 421 | int sqliteExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqliteExprResolveIds(Parse*, IdList*, Expr*); void sqliteExprResolveInSelect(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); void sqliteParseInfoReset(Parse*); Vdbe *sqliteGetVdbe(Parse*); | > > > > > | 415 416 417 418 419 420 421 422 423 424 425 426 | int sqliteExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqliteExprResolveIds(Parse*, IdList*, Expr*); void sqliteExprResolveInSelect(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); void sqliteParseInfoReset(Parse*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); int sqliteRandomInteger(void); void sqliteRandomName(char*,char*); int sqliteDbbeOpenTempFile(Dbbe*, FILE**); void sqliteDbbeCloseTempFile(Dbbe*, FILE*); |
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.50 2001/01/13 14:34:07 drh Exp $ */ #include "sqliteInt.h" #include <unistd.h> #include <ctype.h> /* ** SQL is translated into a sequence of instructions to be |
︙ | ︙ | |||
692 693 694 695 696 697 698 | static void Cleanup(Vdbe *p){ int i; PopStack(p, p->tos+1); sqliteFree(p->azColName); p->azColName = 0; for(i=0; i<p->nCursor; i++){ if( p->aCsr[i].pCursor ){ | | | | 692 693 694 695 696 697 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 | static void Cleanup(Vdbe *p){ int i; PopStack(p, p->tos+1); sqliteFree(p->azColName); p->azColName = 0; for(i=0; i<p->nCursor; i++){ if( p->aCsr[i].pCursor ){ p->pBe->x->CloseCursor(p->aCsr[i].pCursor); p->aCsr[i].pCursor = 0; } } sqliteFree(p->aCsr); p->aCsr = 0; p->nCursor = 0; for(i=0; i<p->nMem; i++){ if( p->aMem[i].s.flags & STK_Dyn ){ sqliteFree(p->aMem[i].z); } } sqliteFree(p->aMem); p->aMem = 0; p->nMem = 0; for(i=0; i<p->nList; i++){ if( p->apList[i] ){ p->pBe->x->CloseTempFile(p->pBe, p->apList[i]); p->apList[i] = 0; } } sqliteFree(p->apList); p->apList = 0; p->nList = 0; for(i=0; i<p->nSort; i++){ |
︙ | ︙ | |||
949 950 951 952 953 954 955 956 957 958 959 960 961 962 | void *pBusyArg, /* 1st argument to the busy callback */ int (*xBusy)(void*,const char*,int) /* Called when a file is busy */ ){ int pc; /* The program counter */ Op *pOp; /* Current operation */ int rc; /* Value to return */ Dbbe *pBe = p->pBe; /* The backend driver */ sqlite *db = p->db; /* The database */ char **zStack; Stack *aStack; char zBuf[100]; /* Space to sprintf() and integer */ /* No instruction ever pushes more than a single element onto the | > | 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 | void *pBusyArg, /* 1st argument to the busy callback */ int (*xBusy)(void*,const char*,int) /* Called when a file is busy */ ){ int pc; /* The program counter */ Op *pOp; /* Current operation */ int rc; /* Value to return */ Dbbe *pBe = p->pBe; /* The backend driver */ DbbeMethods *pBex = pBe->x; /* The backend driver methods */ sqlite *db = p->db; /* The database */ char **zStack; Stack *aStack; char zBuf[100]; /* Space to sprintf() and integer */ /* No instruction ever pushes more than a single element onto the |
︙ | ︙ | |||
1805 1806 1807 1808 1809 1810 1811 | if( i>=p->nCursor ){ int j; p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) ); if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; } for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0; p->nCursor = i+1; }else if( p->aCsr[i].pCursor ){ | | | | 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 | if( i>=p->nCursor ){ int j; p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) ); if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; } for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0; p->nCursor = i+1; }else if( p->aCsr[i].pCursor ){ pBex->CloseCursor(p->aCsr[i].pCursor); } do { rc = pBex->OpenCursor(pBe,pOp->p3,pOp->p2,&p->aCsr[i].pCursor); switch( rc ){ case SQLITE_BUSY: { if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){ sqliteSetString(pzErrMsg,"table ", pOp->p3, " is locked", 0); busy = 0; } break; |
︙ | ︙ | |||
1849 1850 1851 1852 1853 1854 1855 | ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ case OP_Close: { int i = pOp->p1; if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){ | | | | | 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 | ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. */ case OP_Close: { int i = pOp->p1; if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){ pBex->CloseCursor(p->aCsr[i].pCursor); p->aCsr[i].pCursor = 0; } break; } /* Opcode: Fetch P1 * * ** ** Pop the top of the stack and use its value as a key to fetch ** a record from cursor P1. The key/data pair is held ** in the P1 cursor until needed. */ case OP_Fetch: { int i = pOp->p1; int tos = p->tos; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){ if( aStack[tos].flags & STK_Int ){ pBex->Fetch(p->aCsr[i].pCursor, sizeof(int), (char*)&aStack[tos].i); }else{ if( Stringify(p, tos) ) goto no_mem; pBex->Fetch(p->aCsr[i].pCursor, aStack[tos].n, zStack[tos]); } p->nFetch++; } POPSTACK; break; } |
︙ | ︙ | |||
1933 1934 1935 1936 1937 1938 1939 | case OP_Found: { int i = pOp->p1; int tos = p->tos; int alreadyExists = 0; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor ){ if( aStack[tos].flags & STK_Int ){ | | | | 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 | case OP_Found: { int i = pOp->p1; int tos = p->tos; int alreadyExists = 0; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor ){ if( aStack[tos].flags & STK_Int ){ alreadyExists = pBex->Test(p->aCsr[i].pCursor, sizeof(int), (char*)&aStack[tos].i); }else{ if( Stringify(p, tos) ) goto no_mem; alreadyExists = pBex->Test(p->aCsr[i].pCursor,aStack[tos].n, zStack[tos]); } } if( pOp->opcode==OP_Found ){ if( alreadyExists ) pc = pOp->p2 - 1; }else{ if( !alreadyExists ) pc = pOp->p2 - 1; |
︙ | ︙ | |||
1963 1964 1965 1966 1967 1968 1969 | */ case OP_New: { int i = pOp->p1; int v; if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){ v = 0; }else{ | | | 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 | */ case OP_New: { int i = pOp->p1; int v; if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){ v = 0; }else{ v = pBex->New(p->aCsr[i].pCursor); } VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].i = v; aStack[p->tos].flags = STK_Int; break; } |
︙ | ︙ | |||
1996 1997 1998 1999 2000 2001 2002 | if( Stringify(p, nos) ) goto no_mem; nKey = aStack[nos].n; zKey = zStack[nos]; }else{ nKey = sizeof(int); zKey = (char*)&aStack[nos].i; } | | | 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 | if( Stringify(p, nos) ) goto no_mem; nKey = aStack[nos].n; zKey = zStack[nos]; }else{ nKey = sizeof(int); zKey = (char*)&aStack[nos].i; } pBex->Put(p->aCsr[i].pCursor, nKey, zKey, aStack[tos].n, zStack[tos]); } POPSTACK; POPSTACK; break; } |
︙ | ︙ | |||
2024 2025 2026 2027 2028 2029 2030 | nKey = sizeof(int); zKey = (char*)&aStack[tos].i; }else{ if( Stringify(p, tos) ) goto no_mem; nKey = aStack[tos].n; zKey = zStack[tos]; } | | | 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 | nKey = sizeof(int); zKey = (char*)&aStack[tos].i; }else{ if( Stringify(p, tos) ) goto no_mem; nKey = aStack[tos].n; zKey = zStack[tos]; } pBex->Delete(p->aCsr[i].pCursor, nKey, zKey); } POPSTACK; break; } /* Opcode: KeyAsData P1 P2 * ** |
︙ | ︙ | |||
2078 2079 2080 2081 2082 2083 2084 | int tos = ++p->tos; DbbeCursor *pCrsr; char *z; VERIFY( if( NeedStack(p, tos) ) goto no_mem; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ if( p->aCsr[i].keyAsData ){ | | | | | | | | 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 | int tos = ++p->tos; DbbeCursor *pCrsr; char *z; VERIFY( if( NeedStack(p, tos) ) goto no_mem; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ if( p->aCsr[i].keyAsData ){ amt = pBex->KeyLength(pCrsr); if( amt<=sizeof(int)*(p2+1) ){ aStack[tos].flags = STK_Null; break; } pAddr = (int*)pBex->ReadKey(pCrsr, sizeof(int)*p2); if( *pAddr==0 ){ aStack[tos].flags = STK_Null; break; } z = pBex->ReadKey(pCrsr, *pAddr); }else{ amt = pBex->DataLength(pCrsr); if( amt<=sizeof(int)*(p2+1) ){ aStack[tos].flags = STK_Null; break; } pAddr = (int*)pBex->ReadData(pCrsr, sizeof(int)*p2); if( *pAddr==0 ){ aStack[tos].flags = STK_Null; break; } z = pBex->ReadData(pCrsr, *pAddr); } zStack[tos] = z; aStack[tos].n = strlen(z) + 1; aStack[tos].flags = STK_Str; } break; } |
︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 | case OP_Key: { int i = pOp->p1; int tos = ++p->tos; DbbeCursor *pCrsr; VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ | | | | | | 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 | case OP_Key: { int i = pOp->p1; int tos = ++p->tos; DbbeCursor *pCrsr; VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ char *z = pBex->ReadKey(pCrsr, 0); if( p->aCsr[i].keyAsData ){ zStack[tos] = z; aStack[tos].flags = STK_Str; aStack[tos].n = pBex->KeyLength(pCrsr); }else{ memcpy(&aStack[tos].i, z, sizeof(int)); aStack[tos].flags = STK_Int; } } break; } /* Opcode: Rewind P1 * * ** ** The next use of the Key or Field or Next instruction for P1 ** will refer to the first entry in the database file. */ case OP_Rewind: { int i = pOp->p1; if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){ pBex->Rewind(p->aCsr[i].pCursor); } break; } /* Opcode: Next P1 P2 * ** ** Advance P1 to the next key/data pair in the file. Or, if there are no ** more key/data pairs, rewind P1 and jump to location P2. */ case OP_Next: { int i = pOp->p1; if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){ if( pBex->NextKey(p->aCsr[i].pCursor)==0 ){ pc = pOp->p2 - 1; }else{ p->nFetch++; } } break; } |
︙ | ︙ | |||
2207 2208 2209 2210 2211 2212 2213 | VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) zStack[tos] = 0; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int *aIdx; int nIdx; int j, k; | | | | 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 | VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) zStack[tos] = 0; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int *aIdx; int nIdx; int j, k; nIdx = pBex->DataLength(pCrsr)/sizeof(int); aIdx = (int*)pBex->ReadData(pCrsr, 0); if( nIdx>1 ){ k = *(aIdx++); if( k>nIdx-1 ) k = nIdx-1; }else{ k = nIdx; } for(j=p->aCsr[i].index; j<k; j++){ |
︙ | ︙ | |||
2253 2254 2255 2256 2257 2258 2259 | VERIFY( if( nos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int r; int newVal; Integerify(p, nos); newVal = aStack[nos].i; if( Stringify(p, tos) ) goto no_mem; | | | | | | | | | | | 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 | VERIFY( if( nos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int r; int newVal; Integerify(p, nos); newVal = aStack[nos].i; if( Stringify(p, tos) ) goto no_mem; r = pBex->Fetch(pCrsr, aStack[tos].n, zStack[tos]); if( r==0 ){ /* Create a new record for this index */ pBex->Put(pCrsr, aStack[tos].n, zStack[tos], sizeof(int), (char*)&newVal); }else{ /* Extend the existing record */ int nIdx; int *aIdx; int k; nIdx = pBex->DataLength(pCrsr)/sizeof(int); if( nIdx==1 ){ aIdx = sqliteMalloc( sizeof(int)*4 ); if( aIdx==0 ) goto no_mem; aIdx[0] = 2; pBex->CopyData(pCrsr, 0, sizeof(int), (char*)&aIdx[1]); aIdx[2] = newVal; pBex->Put(pCrsr, aStack[tos].n, zStack[tos], sizeof(int)*4, (char*)aIdx); sqliteFree(aIdx); }else{ aIdx = (int*)pBex->ReadData(pCrsr, 0); k = aIdx[0]; if( k<nIdx-1 ){ aIdx[k+1] = newVal; aIdx[0]++; pBex->Put(pCrsr, aStack[tos].n, zStack[tos], sizeof(int)*nIdx, (char*)aIdx); }else{ nIdx *= 2; aIdx = sqliteMalloc( sizeof(int)*nIdx ); if( aIdx==0 ) goto no_mem; pBex->CopyData(pCrsr, 0, sizeof(int)*(k+1), (char*)aIdx); aIdx[k+1] = newVal; aIdx[0]++; pBex->Put(pCrsr, aStack[tos].n, zStack[tos], sizeof(int)*nIdx, (char*)aIdx); sqliteFree(aIdx); } } } } POPSTACK; |
︙ | ︙ | |||
2329 2330 2331 2332 2333 2334 2335 | int nIdx; int j, k; int r; int oldVal; Integerify(p, nos); oldVal = aStack[nos].i; if( Stringify(p, tos) ) goto no_mem; | | | | | | | | | 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 | int nIdx; int j, k; int r; int oldVal; Integerify(p, nos); oldVal = aStack[nos].i; if( Stringify(p, tos) ) goto no_mem; r = pBex->Fetch(pCrsr, aStack[tos].n, zStack[tos]); if( r==0 ) break; nIdx = pBex->DataLength(pCrsr)/sizeof(int); aIdx = (int*)pBex->ReadData(pCrsr, 0); if( (nIdx==1 && aIdx[0]==oldVal) || (aIdx[0]==1 && aIdx[1]==oldVal) ){ pBex->Delete(pCrsr, aStack[tos].n, zStack[tos]); }else{ k = aIdx[0]; for(j=1; j<=k && aIdx[j]!=oldVal; j++){} if( j>k ) break; aIdx[j] = aIdx[k]; aIdx[k] = 0; aIdx[0]--; if( aIdx[0]*3 + 1 < nIdx ){ nIdx /= 2; } pBex->Put(pCrsr, aStack[tos].n, zStack[tos], sizeof(int)*nIdx, (char*)aIdx); } } POPSTACK; POPSTACK; break; } /* Opcode: Destroy * * P3 ** ** Drop the disk file whose name is P3. All key/data pairs in ** the file are deleted and the file itself is removed ** from the disk. */ case OP_Destroy: { pBex->DropTable(pBe, pOp->p3); break; } /* Opcode: Reorganize * * P3 ** ** Compress, optimize, and tidy up the GDBM file named by P3. */ case OP_Reorganize: { pBex->ReorganizeTable(pBe, pOp->p3); break; } /* Opcode: ListOpen P1 * * ** ** Open a file used for temporary storage of integer table keys. P1 ** will server as a handle to this temporary file for future |
︙ | ︙ | |||
2392 2393 2394 2395 2396 2397 2398 | if( i>=p->nList ){ int j; p->apList = sqliteRealloc( p->apList, (i+1)*sizeof(FILE*) ); if( p->apList==0 ){ p->nList = 0; goto no_mem; } for(j=p->nList; j<=i; j++) p->apList[j] = 0; p->nList = i+1; }else if( p->apList[i] ){ | | | | 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 | if( i>=p->nList ){ int j; p->apList = sqliteRealloc( p->apList, (i+1)*sizeof(FILE*) ); if( p->apList==0 ){ p->nList = 0; goto no_mem; } for(j=p->nList; j<=i; j++) p->apList[j] = 0; p->nList = i+1; }else if( p->apList[i] ){ pBex->CloseTempFile(pBe, p->apList[i]); } rc = pBex->OpenTempFile(pBe, &p->apList[i]); if( rc!=SQLITE_OK ){ sqliteSetString(pzErrMsg, "unable to open a temporary file", 0); } break; } /* Opcode: ListWrite P1 * * |
︙ | ︙ | |||
2464 2465 2466 2467 2468 2469 2470 | ** ** Close the temporary storage buffer and discard its contents. */ case OP_ListClose: { int i = pOp->p1; VERIFY( if( i<0 ) goto bad_instruction; ) if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){ | | | 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 | ** ** Close the temporary storage buffer and discard its contents. */ case OP_ListClose: { int i = pOp->p1; VERIFY( if( i<0 ) goto bad_instruction; ) if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){ pBex->CloseTempFile(pBe, p->apList[i]); p->apList[i] = 0; } break; } /* Opcode: SortOpen P1 * * ** |
︙ | ︙ |