1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

(1) Modifications to the user-function interface and (2) Internal changes

to automatically created indices. (CVS 1575)

FossilOrigin-Name: 5903f53828b5d282b33e27813417e4317c9ecf0b
This commit is contained in:
danielk1977
2004-06-12 09:25:12 +00:00
parent 3cde3bb0da
commit d8123366c4
23 changed files with 618 additions and 337 deletions

View File

@@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.217 2004/06/12 00:42:35 danielk1977 Exp $
** $Id: build.c,v 1.218 2004/06/12 09:25:12 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -479,6 +479,21 @@ int sqlite3TwoPartName(
return iDb;
}
/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
** trigger). All names are legal except those that begin with the string
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
}
return SQLITE_OK;
}
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
@@ -541,6 +556,9 @@ void sqlite3StartTable(
pParse->sNameToken = *pName;
zName = sqlite3TableNameFromToken(pName);
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
return;
}
if( zName==0 ) return;
if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -1854,7 +1872,7 @@ void sqlite3CreateIndex(
Token *pEnd /* The ")" that closes the CREATE INDEX statement */
){
Table *pTab = 0; /* Table to be indexed */
Index *pIndex; /* The index to be created */
Index *pIndex = 0; /* The index to be created */
char *zName = 0;
int i, j;
Token nullId; /* Fake token for an empty ID list */
@@ -1927,30 +1945,33 @@ void sqlite3CreateIndex(
** dealing with a primary key or UNIQUE constraint. We have to invent our
** own name.
*/
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( pName ){
zName = sqlite3TableNameFromToken(pName);
if( zName==0 ) goto exit_create_index;
if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto exit_create_index;
}
if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){
sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
if( !db->init.busy ){
Index *pISameName; /* Another index with the same name */
Table *pTSameName; /* A table with same name as the index */
if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
goto exit_create_index;
}
if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){
sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
}
}
}else if( pName==0 ){
char zBuf[30];
int n;
Index *pLoop;
for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
sprintf(zBuf,"%d)",n);
sprintf(zBuf,"_%d",n);
zName = 0;
sqlite3SetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
sqlite3SetString(&zName, "sqlite_autoindex_", pTab->zName, zBuf, (char*)0);
if( zName==0 ) goto exit_create_index;
}else{
zName = sqliteStrNDup(pName->z, pName->n);
}
/* Check for authorization to create an index.
@@ -2006,7 +2027,6 @@ void sqlite3CreateIndex(
if( j>=pTab->nCol ){
sqlite3ErrorMsg(pParse, "table %s has no column named %s",
pTab->zName, pList->a[i].zName);
sqliteFree(pIndex);
goto exit_create_index;
}
pIndex->aiColumn[i] = j;
@@ -2025,6 +2045,46 @@ void sqlite3CreateIndex(
}
pIndex->keyInfo.nField = pList->nExpr;
if( pTab==pParse->pNewTable ){
/* This routine has been called to create an automatic index as a
** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
** a PRIMARY KEY or UNIQUE clause following the column definitions.
** i.e. one of:
**
** CREATE TABLE t(x PRIMARY KEY, y);
** CREATE TABLE t(x, y, UNIQUE(x, y));
**
** Either way, check to see if the table already has such an index. If
** so, don't bother creating this one. This only applies to
** automatically created indices. Users can do as they wish with
** explicit indices.
*/
Index *pIdx;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int k;
assert( pIdx->onError!=OE_None );
assert( pIdx->autoIndex );
assert( pIndex->onError!=OE_None );
if( pIdx->nColumn!=pIndex->nColumn ) continue;
for(k=0; k<pIdx->nColumn; k++){
if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) break;
}
if( k==pIdx->nColumn ){
/* FIX ME: It's possible the onError of the old index should be
** adjusted. For example in the statement:
**
** CREATE TABLE t (x UNIQUE, UNIQUE(x) ON CONFLICT ROLLBACK);
**
** The Index.onError should be upgraded from OE_Abort to
** OE_Rollback when the second UNIQUE is parsed.
*/
goto exit_create_index;
}
}
}
/* Link the new Index structure to its table and to the other
** in-memory database structures.
*/
@@ -2034,30 +2094,11 @@ void sqlite3CreateIndex(
pIndex->zName, strlen(pIndex->zName)+1, pIndex);
if( p ){
assert( p==pIndex ); /* Malloc must have failed */
sqliteFree(pIndex);
goto exit_create_index;
}
db->flags |= SQLITE_InternChanges;
}
/* When adding an index to the list of indices for a table, make
** sure all indices labeled OE_Replace come after all those labeled
** OE_Ignore. This is necessary for the correct operation of UPDATE
** and INSERT.
*/
if( onError!=OE_Replace || pTab->pIndex==0
|| pTab->pIndex->onError==OE_Replace){
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
}else{
Index *pOther = pTab->pIndex;
while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
pOther = pOther->pNext;
}
pIndex->pNext = pOther->pNext;
pOther->pNext = pIndex;
}
/* 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 db->init.newTnum field.
@@ -2145,8 +2186,28 @@ void sqlite3CreateIndex(
}
}
/* When adding an index to the list of indices for a table, make
** sure all indices labeled OE_Replace come after all those labeled
** OE_Ignore. This is necessary for the correct operation of UPDATE
** and INSERT.
*/
if( onError!=OE_Replace || pTab->pIndex==0
|| pTab->pIndex->onError==OE_Replace){
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
}else{
Index *pOther = pTab->pIndex;
while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
pOther = pOther->pNext;
}
pIndex->pNext = pOther->pNext;
pOther->pNext = pIndex;
}
pIndex = 0;
/* Clean up before exiting */
exit_create_index:
if( pIndex ) sqliteFree(pIndex);
sqlite3ExprListDelete(pList);
/* sqlite3SrcListDelete(pTable); */
sqliteFree(zName);