mirror of
https://github.com/php/php-src.git
synced 2025-08-20 01:14:28 +02:00
Upgrade bundled library to 2.8.14 + misc fixes
(http://www.sqlite.org/cvstrac/chngview?cn=1742)
This commit is contained in:
parent
cd732f1a3f
commit
e563b4eafa
43 changed files with 5953 additions and 5559 deletions
|
@ -38,7 +38,7 @@ void sqliteBeginParse(Parse *pParse, int explainFlag){
|
|||
sqlite *db = pParse->db;
|
||||
int i;
|
||||
pParse->explain = explainFlag;
|
||||
if((db->flags & SQLITE_Initialized)==0 && pParse->initFlag==0 ){
|
||||
if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
|
||||
int rc = sqliteInit(db, &pParse->zErrMsg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pParse->rc = rc;
|
||||
|
@ -54,17 +54,6 @@ void sqliteBeginParse(Parse *pParse, int explainFlag){
|
|||
pParse->nVar = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a fake callback procedure used when sqlite_exec() is
|
||||
** invoked with a NULL callback pointer. If we pass a NULL callback
|
||||
** pointer into sqliteVdbeExec() it will return at every OP_Callback,
|
||||
** which we do not want it to do. So we substitute a pointer to this
|
||||
** procedure in place of the NULL.
|
||||
*/
|
||||
static int fakeCallback(void *NotUsed, int n, char **az1, char **az2){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called after a single SQL statement has been
|
||||
** parsed and we want to execute the VDBE code to implement
|
||||
|
@ -76,36 +65,20 @@ static int fakeCallback(void *NotUsed, int n, char **az1, char **az2){
|
|||
** no VDBE code was generated.
|
||||
*/
|
||||
void sqliteExec(Parse *pParse){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite *db = pParse->db;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int (*xCallback)(void*,int,char**,char**);
|
||||
|
||||
if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){
|
||||
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
|
||||
}
|
||||
if( sqlite_malloc_failed ) return;
|
||||
xCallback = pParse->xCallback;
|
||||
if( xCallback==0 && pParse->useCallback ) xCallback = fakeCallback;
|
||||
if( v && pParse->nErr==0 ){
|
||||
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
|
||||
sqliteVdbeTrace(v, trace);
|
||||
sqliteVdbeMakeReady(v, pParse->nVar, xCallback, pParse->pArg,
|
||||
pParse->explain);
|
||||
if( pParse->useCallback ){
|
||||
if( pParse->explain ){
|
||||
rc = sqliteVdbeList(v);
|
||||
db->next_cookie = db->aDb[0].schema_cookie;
|
||||
}else{
|
||||
sqliteVdbeExec(v);
|
||||
}
|
||||
rc = sqliteVdbeFinalize(v, &pParse->zErrMsg);
|
||||
if( rc ) pParse->nErr++;
|
||||
pParse->pVdbe = 0;
|
||||
pParse->rc = rc;
|
||||
if( rc ) pParse->nErr++;
|
||||
}else{
|
||||
pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
|
||||
}
|
||||
sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain);
|
||||
pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
|
||||
pParse->colNamesSet = 0;
|
||||
}else if( pParse->useCallback==0 ){
|
||||
}else if( pParse->rc==SQLITE_OK ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
pParse->nTab = 0;
|
||||
|
@ -240,7 +213,7 @@ void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
|
|||
**
|
||||
** If iDb<=0 then reset the internal schema tables for all database
|
||||
** files. If iDb>=2 then reset the internal schema for only the
|
||||
** single file indicates.
|
||||
** single file indicated.
|
||||
*/
|
||||
void sqliteResetInternalSchema(sqlite *db, int iDb){
|
||||
HashElem *pElem;
|
||||
|
@ -280,10 +253,18 @@ void sqliteResetInternalSchema(sqlite *db, int iDb){
|
|||
** schema hash tables and therefore do not have to make any changes
|
||||
** to any of those tables.
|
||||
*/
|
||||
for(i=0; i<db->nDb; i++){
|
||||
struct Db *pDb = &db->aDb[i];
|
||||
if( pDb->pBt==0 ){
|
||||
if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
|
||||
pDb->pAux = 0;
|
||||
}
|
||||
}
|
||||
for(i=j=2; i<db->nDb; i++){
|
||||
if( db->aDb[i].pBt==0 ){
|
||||
sqliteFree(db->aDb[i].zName);
|
||||
db->aDb[i].zName = 0;
|
||||
struct Db *pDb = &db->aDb[i];
|
||||
if( pDb->pBt==0 ){
|
||||
sqliteFree(pDb->zName);
|
||||
pDb->zName = 0;
|
||||
continue;
|
||||
}
|
||||
if( j<i ){
|
||||
|
@ -456,7 +437,7 @@ void sqliteStartTable(
|
|||
pParse->sFirstToken = *pStart;
|
||||
zName = sqliteTableNameFromToken(pName);
|
||||
if( zName==0 ) return;
|
||||
if( pParse->iDb==1 ) isTemp = 1;
|
||||
if( db->init.iDb==1 ) isTemp = 1;
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
assert( (isTemp & 1)==isTemp );
|
||||
{
|
||||
|
@ -493,17 +474,16 @@ void sqliteStartTable(
|
|||
if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){
|
||||
int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqliteSetString(&pParse->zErrMsg, "unable to open a temporary database "
|
||||
"file for storing temporary tables", (char*)0);
|
||||
sqliteErrorMsg(pParse, "unable to open a temporary database "
|
||||
"file for storing temporary tables");
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
if( db->flags & SQLITE_InTrans ){
|
||||
rc = sqliteBtreeBeginTrans(db->aDb[1].pBt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqliteSetNString(&pParse->zErrMsg, "unable to get a write lock on "
|
||||
"the temporary database file", 0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "unable to get a write lock on "
|
||||
"the temporary database file");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -517,20 +497,16 @@ void sqliteStartTable(
|
|||
** an existing temporary table, that is not an error.
|
||||
*/
|
||||
pTable = sqliteFindTable(db, zName, 0);
|
||||
iDb = isTemp ? 1 : pParse->iDb;
|
||||
if( pTable!=0 && (pTable->iDb==iDb || !pParse->initFlag) ){
|
||||
sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
|
||||
" already exists", 0, 0);
|
||||
iDb = isTemp ? 1 : db->init.iDb;
|
||||
if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
|
||||
sqliteErrorMsg(pParse, "table %T already exists", pName);
|
||||
sqliteFree(zName);
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
|
||||
(pIdx->iDb==0 || !pParse->initFlag) ){
|
||||
sqliteSetString(&pParse->zErrMsg, "there is already an index named ",
|
||||
zName, (char*)0);
|
||||
(pIdx->iDb==0 || !db->init.busy) ){
|
||||
sqliteErrorMsg(pParse, "there is already an index named %s", zName);
|
||||
sqliteFree(zName);
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
pTable = sqliteMalloc( sizeof(Table) );
|
||||
|
@ -555,7 +531,7 @@ void sqliteStartTable(
|
|||
** indices. Hence, the record number for the table must be allocated
|
||||
** now.
|
||||
*/
|
||||
if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
|
||||
if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
|
||||
sqliteBeginWriteOperation(pParse, 0, isTemp);
|
||||
if( !isTemp ){
|
||||
sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
|
||||
|
@ -588,8 +564,7 @@ void sqliteAddColumn(Parse *pParse, Token *pName){
|
|||
sqliteDequote(z);
|
||||
for(i=0; i<p->nCol; i++){
|
||||
if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){
|
||||
sqliteSetString(&pParse->zErrMsg, "duplicate column name: ", z, (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "duplicate column name: %s", z);
|
||||
sqliteFree(z);
|
||||
return;
|
||||
}
|
||||
|
@ -708,9 +683,8 @@ void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
|
|||
int iCol = -1, i;
|
||||
if( pTab==0 ) goto primary_key_exit;
|
||||
if( pTab->hasPrimKey ){
|
||||
sqliteSetString(&pParse->zErrMsg, "table \"", pTab->zName,
|
||||
"\" has more than one primary key", (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse,
|
||||
"table \"%s\" has more than one primary key", pTab->zName);
|
||||
goto primary_key_exit;
|
||||
}
|
||||
pTab->hasPrimKey = 1;
|
||||
|
@ -753,34 +727,16 @@ primary_key_exit:
|
|||
*/
|
||||
int sqliteCollateType(const char *zType, int nType){
|
||||
int i;
|
||||
for(i=0; i<nType-1; i++){
|
||||
switch( zType[i] ){
|
||||
case 'b':
|
||||
case 'B': {
|
||||
if( i<nType-3 && sqliteStrNICmp(&zType[i],"blob",4)==0 ){
|
||||
return SQLITE_SO_TEXT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
case 'C': {
|
||||
if( i<nType-3 && (sqliteStrNICmp(&zType[i],"char",4)==0 ||
|
||||
sqliteStrNICmp(&zType[i],"clob",4)==0)
|
||||
){
|
||||
return SQLITE_SO_TEXT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'x':
|
||||
case 'X': {
|
||||
if( i>=2 && sqliteStrNICmp(&zType[i-2],"text",4)==0 ){
|
||||
return SQLITE_SO_TEXT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
for(i=0; i<nType-3; i++){
|
||||
int c = *(zType++) | 0x60;
|
||||
if( (c=='b' || c=='c') && sqliteStrNICmp(zType, "lob", 3)==0 ){
|
||||
return SQLITE_SO_TEXT;
|
||||
}
|
||||
if( c=='c' && sqliteStrNICmp(zType, "har", 3)==0 ){
|
||||
return SQLITE_SO_TEXT;
|
||||
}
|
||||
if( c=='t' && sqliteStrNICmp(zType, "ext", 3)==0 ){
|
||||
return SQLITE_SO_TEXT;
|
||||
}
|
||||
}
|
||||
return SQLITE_SO_NUM;
|
||||
|
@ -819,7 +775,9 @@ void sqliteAddCollateType(Parse *pParse, int collType){
|
|||
*/
|
||||
void sqliteChangeCookie(sqlite *db, Vdbe *v){
|
||||
if( db->next_cookie==db->aDb[0].schema_cookie ){
|
||||
db->next_cookie = db->aDb[0].schema_cookie + sqliteRandomByte() + 1;
|
||||
unsigned char r;
|
||||
sqliteRandomness(1, &r);
|
||||
db->next_cookie = db->aDb[0].schema_cookie + r + 1;
|
||||
db->flags |= SQLITE_InternChanges;
|
||||
sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
|
||||
sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
|
||||
|
@ -910,8 +868,8 @@ static char *createTableStmt(Table *p){
|
|||
** is added to the internal hash tables, assuming no errors have
|
||||
** occurred.
|
||||
**
|
||||
** An entry for the table is made in the master table on disk,
|
||||
** unless this is a temporary table or initFlag==1. When initFlag==1,
|
||||
** An entry for the table is made in the master table on disk, unless
|
||||
** this is a temporary table or db->init.busy==1. When db->init.busy==1
|
||||
** it means we are reading the sqlite_master table because we just
|
||||
** connected to the database or because the sqlite_master table has
|
||||
** recently changes, so the entry for this table already exists in
|
||||
|
@ -944,14 +902,14 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
|
|||
sqliteDeleteTable(0, pSelTab);
|
||||
}
|
||||
|
||||
/* If the initFlag is 1 it means we are reading the SQL off the
|
||||
/* If the db->init.busy is 1 it means we are reading the SQL off the
|
||||
** "sqlite_master" or "sqlite_temp_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
|
||||
** for the table from the db->init.newTnum field. (The page number
|
||||
** should have been put there by the sqliteOpenCb routine.)
|
||||
*/
|
||||
if( pParse->initFlag ){
|
||||
p->tnum = pParse->newTnum;
|
||||
if( db->init.busy ){
|
||||
p->tnum = db->init.newTnum;
|
||||
}
|
||||
|
||||
/* If not initializing, then create a record for the new table
|
||||
|
@ -961,7 +919,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
|
|||
** If this is a TEMPORARY table, write the entry into the auxiliary
|
||||
** file instead of into the main database file.
|
||||
*/
|
||||
if( !pParse->initFlag ){
|
||||
if( !db->init.busy ){
|
||||
int n;
|
||||
Vdbe *v;
|
||||
|
||||
|
@ -969,24 +927,16 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
|
|||
if( v==0 ) return;
|
||||
if( p->pSelect==0 ){
|
||||
/* A regular table */
|
||||
sqliteVdbeAddOp(v, OP_CreateTable, 0, p->iDb);
|
||||
sqliteVdbeChangeP3(v, -1, (char *)&p->tnum, P3_POINTER);
|
||||
sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
|
||||
}else{
|
||||
/* A view */
|
||||
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
|
||||
}
|
||||
p->tnum = 0;
|
||||
sqliteVdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
if( p->pSelect==0 ){
|
||||
sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
|
||||
}else{
|
||||
sqliteVdbeChangeP3(v, -1, "view", P3_STATIC);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
|
||||
sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
|
||||
sqliteVdbeAddOp(v, OP_Dup, 4, 0);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
if( pSelect ){
|
||||
|
@ -1072,7 +1022,7 @@ void sqliteCreateView(
|
|||
*/
|
||||
p->pSelect = sqliteSelectDup(pSelect);
|
||||
sqliteSelectDelete(pSelect);
|
||||
if( !pParse->initFlag ){
|
||||
if( !pParse->db->init.busy ){
|
||||
sqliteViewGetColumnNames(pParse, p);
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1034,7 @@ void sqliteCreateView(
|
|||
sEnd.z += sEnd.n;
|
||||
}
|
||||
sEnd.n = 0;
|
||||
n = (char *) sEnd.z - (char *) pBegin->z;
|
||||
n = sEnd.z - pBegin->z;
|
||||
z = pBegin->z;
|
||||
while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
|
||||
sEnd.z = &z[n-1];
|
||||
|
@ -1098,7 +1048,7 @@ void sqliteCreateView(
|
|||
/*
|
||||
** The Table structure pTable is really a VIEW. Fill in the names of
|
||||
** the columns of the view in the pTable structure. Return the number
|
||||
** of errors. If an error is seen leave an error message in pPare->zErrMsg.
|
||||
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
|
||||
*/
|
||||
int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
ExprList *pEList;
|
||||
|
@ -1124,9 +1074,7 @@ int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
|
|||
** should always fail. But we will leave it in place just to be safe.
|
||||
*/
|
||||
if( pTable->nCol<0 ){
|
||||
sqliteSetString(&pParse->zErrMsg, "view ", pTable->zName,
|
||||
" is circularly defined", (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1176,12 +1124,12 @@ int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
|
|||
*/
|
||||
static void sqliteViewResetColumnNames(Table *pTable){
|
||||
int i;
|
||||
if( pTable==0 || pTable->pSelect==0 ) return;
|
||||
if( pTable->nCol==0 ) return;
|
||||
for(i=0; i<pTable->nCol; i++){
|
||||
sqliteFree(pTable->aCol[i].zName);
|
||||
sqliteFree(pTable->aCol[i].zDflt);
|
||||
sqliteFree(pTable->aCol[i].zType);
|
||||
Column *pCol;
|
||||
assert( pTable!=0 && pTable->pSelect!=0 );
|
||||
for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
|
||||
sqliteFree(pCol->zName);
|
||||
sqliteFree(pCol->zDflt);
|
||||
sqliteFree(pCol->zType);
|
||||
}
|
||||
sqliteFree(pTable->aCol);
|
||||
pTable->aCol = 0;
|
||||
|
@ -1215,9 +1163,7 @@ Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
|
|||
pTab = sqliteFindTable(pParse->db, zName, 0);
|
||||
sqliteFree(zName);
|
||||
if( pTab==0 ){
|
||||
sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0,
|
||||
pTok->z, pTok->n, 0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "no such table: %T", pTok);
|
||||
}
|
||||
return pTab;
|
||||
}
|
||||
|
@ -1268,21 +1214,16 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){
|
|||
}
|
||||
#endif
|
||||
if( pTable->readOnly ){
|
||||
sqliteSetString(&pParse->zErrMsg, "table ", pTable->zName,
|
||||
" may not be dropped", (char*)0);
|
||||
sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName);
|
||||
pParse->nErr++;
|
||||
return;
|
||||
}
|
||||
if( isView && pTable->pSelect==0 ){
|
||||
sqliteSetString(&pParse->zErrMsg, "use DROP TABLE to delete table ",
|
||||
pTable->zName, (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName);
|
||||
return;
|
||||
}
|
||||
if( !isView && pTable->pSelect ){
|
||||
sqliteSetString(&pParse->zErrMsg, "use DROP VIEW to delete view ",
|
||||
pTable->zName, (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1291,7 +1232,7 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){
|
|||
*/
|
||||
v = sqliteGetVdbe(pParse);
|
||||
if( v ){
|
||||
static VdbeOp dropTable[] = {
|
||||
static VdbeOpList dropTable[] = {
|
||||
{ OP_Rewind, 0, ADDR(8), 0},
|
||||
{ OP_String, 0, 0, 0}, /* 1 */
|
||||
{ OP_MemStore, 1, 1, 0},
|
||||
|
@ -1425,19 +1366,16 @@ void sqliteCreateForeignKey(
|
|||
int iCol = p->nCol-1;
|
||||
if( iCol<0 ) goto fk_end;
|
||||
if( pToCol && pToCol->nId!=1 ){
|
||||
sqliteSetNString(&pParse->zErrMsg, "foreign key on ", -1,
|
||||
p->aCol[iCol].zName, -1,
|
||||
" should reference only one column of table ", -1,
|
||||
pTo->z, pTo->n, 0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "foreign key on %s"
|
||||
" should reference only one column of table %T",
|
||||
p->aCol[iCol].zName, pTo);
|
||||
goto fk_end;
|
||||
}
|
||||
nCol = 1;
|
||||
}else if( pToCol && pToCol->nId!=pFromCol->nId ){
|
||||
sqliteSetString(&pParse->zErrMsg,
|
||||
sqliteErrorMsg(pParse,
|
||||
"number of columns in foreign key does not match the number of "
|
||||
"columns in the referenced table", (char*)0);
|
||||
pParse->nErr++;
|
||||
"columns in the referenced table");
|
||||
goto fk_end;
|
||||
}else{
|
||||
nCol = pFromCol->nId;
|
||||
|
@ -1473,9 +1411,9 @@ void sqliteCreateForeignKey(
|
|||
}
|
||||
}
|
||||
if( j>=p->nCol ){
|
||||
sqliteSetString(&pParse->zErrMsg, "unknown column \"",
|
||||
pFromCol->a[i].zName, "\" in foreign key definition", (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse,
|
||||
"unknown column \"%s\" in foreign key definition",
|
||||
pFromCol->a[i].zName);
|
||||
goto fk_end;
|
||||
}
|
||||
}
|
||||
|
@ -1550,8 +1488,8 @@ void sqliteCreateIndex(
|
|||
sqlite *db = pParse->db;
|
||||
|
||||
if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
|
||||
if( pParse->initFlag
|
||||
&& sqliteFixInit(&sFix, pParse, pParse->iDb, "index", pName)
|
||||
if( db->init.busy
|
||||
&& sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
|
||||
&& sqliteFixSrcList(&sFix, pTable)
|
||||
){
|
||||
goto exit_create_index;
|
||||
|
@ -1570,20 +1508,15 @@ void sqliteCreateIndex(
|
|||
}
|
||||
if( pTab==0 || pParse->nErr ) goto exit_create_index;
|
||||
if( pTab->readOnly ){
|
||||
sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
|
||||
" may not be indexed", (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( pTab->iDb>=2 && pParse->initFlag==0 ){
|
||||
sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
|
||||
" may not have indices added", (char*)0);
|
||||
pParse->nErr++;
|
||||
if( pTab->iDb>=2 && db->init.busy==0 ){
|
||||
sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( pTab->pSelect ){
|
||||
sqliteSetString(&pParse->zErrMsg, "views may not be indexed", (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "views may not be indexed");
|
||||
goto exit_create_index;
|
||||
}
|
||||
isTemp = pTab->iDb==1;
|
||||
|
@ -1601,21 +1534,17 @@ void sqliteCreateIndex(
|
|||
** dealing with a primary key or UNIQUE constraint. We have to invent our
|
||||
** own name.
|
||||
*/
|
||||
if( pName && !pParse->initFlag ){
|
||||
if( pName && !db->init.busy ){
|
||||
Index *pISameName; /* Another index with the same name */
|
||||
Table *pTSameName; /* A table with same name as the index */
|
||||
zName = sqliteStrNDup(pName->z, pName->n);
|
||||
if( zName==0 ) goto exit_create_index;
|
||||
if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
|
||||
sqliteSetString(&pParse->zErrMsg, "index ", zName,
|
||||
" already exists", (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "index %s already exists", zName);
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
|
||||
sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
|
||||
zName, (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "there is already a table named %s", zName);
|
||||
goto exit_create_index;
|
||||
}
|
||||
}else if( pName==0 ){
|
||||
|
@ -1637,7 +1566,7 @@ void sqliteCreateIndex(
|
|||
{
|
||||
const char *zDb = db->aDb[pTab->iDb].zName;
|
||||
|
||||
assert( pTab->iDb==pParse->iDb || isTemp );
|
||||
assert( pTab->iDb==db->init.iDb || isTemp );
|
||||
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
|
@ -1673,7 +1602,7 @@ void sqliteCreateIndex(
|
|||
pIndex->nColumn = pList->nId;
|
||||
pIndex->onError = onError;
|
||||
pIndex->autoIndex = pName==0;
|
||||
pIndex->iDb = isTemp ? 1 : pParse->iDb;
|
||||
pIndex->iDb = isTemp ? 1 : db->init.iDb;
|
||||
|
||||
/* Scan the names of the columns of the table to be indexed and
|
||||
** load the column indices into the Index structure. Report an error
|
||||
|
@ -1684,9 +1613,8 @@ void sqliteCreateIndex(
|
|||
if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
|
||||
}
|
||||
if( j>=pTab->nCol ){
|
||||
sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
|
||||
" has no column named ", pList->a[i].zName, (char*)0);
|
||||
pParse->nErr++;
|
||||
sqliteErrorMsg(pParse, "table %s has no column named %s",
|
||||
pTab->zName, pList->a[i].zName);
|
||||
sqliteFree(pIndex);
|
||||
goto exit_create_index;
|
||||
}
|
||||
|
@ -1726,20 +1654,20 @@ void sqliteCreateIndex(
|
|||
pOther->pNext = pIndex;
|
||||
}
|
||||
|
||||
/* If the initFlag is 1 it means we are reading the SQL off the
|
||||
/* If the db->init.busy is 1 it means we are reading the SQL off the
|
||||
** "sqlite_master" table on the disk. So do not write to the disk
|
||||
** again. Extract the table number from the pParse->newTnum field.
|
||||
** again. Extract the table number from the db->init.newTnum field.
|
||||
*/
|
||||
if( pParse->initFlag && pTable!=0 ){
|
||||
pIndex->tnum = pParse->newTnum;
|
||||
if( db->init.busy && pTable!=0 ){
|
||||
pIndex->tnum = db->init.newTnum;
|
||||
}
|
||||
|
||||
/* If the initFlag is 0 then create the index on disk. This
|
||||
/* If the db->init.busy is 0 then create the index on disk. This
|
||||
** involves writing the index into the master table and filling in the
|
||||
** index with the current table contents.
|
||||
**
|
||||
** The initFlag is 0 when the user first enters a CREATE INDEX
|
||||
** command. The initFlag is 1 when a database is opened and
|
||||
** The db->init.busy is 0 when the user first enters a CREATE INDEX
|
||||
** command. db->init.busy is 1 when a database is opened and
|
||||
** CREATE INDEX statements are read out of the master table. In
|
||||
** the latter case the index already exists on disk, which is why
|
||||
** we don't want to recreate it.
|
||||
|
@ -1749,7 +1677,7 @@ void sqliteCreateIndex(
|
|||
** has just been created, it contains no data and the index initialization
|
||||
** step can be skipped.
|
||||
*/
|
||||
else if( pParse->initFlag==0 ){
|
||||
else if( db->init.busy==0 ){
|
||||
int n;
|
||||
Vdbe *v;
|
||||
int lbl1, lbl2;
|
||||
|
@ -1763,19 +1691,17 @@ void sqliteCreateIndex(
|
|||
sqliteOpenMasterTable(v, isTemp);
|
||||
}
|
||||
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeChangeP3(v, -1, "index", P3_STATIC);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeChangeP3(v, -1, pIndex->zName, P3_STATIC);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
|
||||
addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, isTemp);
|
||||
sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, P3_POINTER);
|
||||
sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0);
|
||||
sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0);
|
||||
sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER);
|
||||
pIndex->tnum = 0;
|
||||
if( pTable ){
|
||||
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
|
||||
sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
|
||||
sqliteVdbeCode(v,
|
||||
OP_Dup, 0, 0,
|
||||
OP_Integer, isTemp, 0,
|
||||
OP_OpenWrite, 1, 0,
|
||||
0);
|
||||
}
|
||||
addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
if( pStart && pEnd ){
|
||||
|
@ -1786,8 +1712,7 @@ void sqliteCreateIndex(
|
|||
sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
|
||||
if( pTable ){
|
||||
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
|
||||
sqliteVdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
|
||||
sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0);
|
||||
lbl2 = sqliteVdbeMakeLabel(v);
|
||||
sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
|
||||
lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
|
||||
|
@ -1801,8 +1726,8 @@ void sqliteCreateIndex(
|
|||
}
|
||||
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
|
||||
if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex);
|
||||
sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->onError!=OE_None);
|
||||
sqliteVdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
|
||||
sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
|
||||
"indexed columns are not unique", P3_STATIC);
|
||||
sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
|
||||
sqliteVdbeResolveLabel(v, lbl2);
|
||||
sqliteVdbeAddOp(v, OP_Close, 2, 0);
|
||||
|
@ -1870,7 +1795,7 @@ void sqliteDropIndex(Parse *pParse, SrcList *pName){
|
|||
/* Generate code to remove the index and from the master table */
|
||||
v = sqliteGetVdbe(pParse);
|
||||
if( v ){
|
||||
static VdbeOp dropIndex[] = {
|
||||
static VdbeOpList dropIndex[] = {
|
||||
{ OP_Rewind, 0, ADDR(9), 0},
|
||||
{ OP_String, 0, 0, 0}, /* 1 */
|
||||
{ OP_MemStore, 1, 1, 0},
|
||||
|
@ -2102,8 +2027,10 @@ void sqliteBeginTransaction(Parse *pParse, int onError){
|
|||
return;
|
||||
}
|
||||
sqliteBeginWriteOperation(pParse, 0, 0);
|
||||
db->flags |= SQLITE_InTrans;
|
||||
db->onError = onError;
|
||||
if( !pParse->explain ){
|
||||
db->flags |= SQLITE_InTrans;
|
||||
db->onError = onError;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2119,9 +2046,13 @@ void sqliteCommitTransaction(Parse *pParse){
|
|||
sqliteErrorMsg(pParse, "cannot commit - no transaction is active");
|
||||
return;
|
||||
}
|
||||
db->flags &= ~SQLITE_InTrans;
|
||||
if( !pParse->explain ){
|
||||
db->flags &= ~SQLITE_InTrans;
|
||||
}
|
||||
sqliteEndWriteOperation(pParse);
|
||||
db->onError = OE_Default;
|
||||
if( !pParse->explain ){
|
||||
db->onError = OE_Default;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2142,8 +2073,10 @@ void sqliteRollbackTransaction(Parse *pParse){
|
|||
if( v ){
|
||||
sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
|
||||
}
|
||||
db->flags &= ~SQLITE_InTrans;
|
||||
db->onError = OE_Default;
|
||||
if( !pParse->explain ){
|
||||
db->flags &= ~SQLITE_InTrans;
|
||||
db->onError = OE_Default;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue