📄 build.c
字号:
pTab = eDbFindTable(pParse->db, zName, 0);
if( pTab==0 ){
eDbErrorMsg(pParse, "no such table: %s", zName);
}
eDbFree(zName);
return pTab;
}
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
void eDbDropTable(Parser *pParse, Token *pName, int isView){
Table *pTable;
ParseResult *pRes;
eDb *db = pParse->db;
if( pParse->nErr || eDb_malloc_failed ) return;
pTable = eDbTableFromToken(pParse, pName);
if( pTable==0 ) return;
/* Delete the in-memory description of the table.
**
** Exception: if the SQL statement began with the EXPLAIN keyword,
** then no changes should be made.
*/
if( !pParse->explain ){
eDbUnlinkTable(db, pTable);
}
pRes = eDbMalloc(sizeof(ParseResult));
pRes->pTable = pTable;
pRes->op = Op_DropTable;
pParse->pResult = pRes;
}
/*
** Create a new index for an SQL table. pIndex is the name of the index
** and pTable is the name of the table that is to be indexed. Both will
** be NULL for a primary key . If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed. pParse->pNewTable is a table that is
** currently being constructed by a CREATE TABLE statement.
**
** pList is a list of columns to be indexed. pList will be NULL if this
** is a primary key on the most recent column added
** to the table currently under construction.
*/
void eDbCreateIndex(
Parser *pParse, /* All information about this parse */
Token *pName, /* Name of the index. May be NULL */
SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */
IdList *pList, /* A list of columns to be indexed */
int onError, /* OP_Unique OP_None */
Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */
Token *pEnd /* The ")" that closes the CREATE INDEX statement */
){
char *zName = 0;
int i, j;
Token nullId; /* Fake token for an empty ID list */
Table *pTab; /* Table to be indexed */
Index *pIndex; /* The index to be created */
ParseResult *pRes;
eDb *db = pParse->db;
if( pParse->nErr || eDb_malloc_failed ) goto exit_create_index;
/*
** Find the table that is to be indexed. Return early if not found.
*/
if( pTable!=0 ){
pTab = eDbSrcListLookup(pParse, pTable);
}else{
pTab = pParse->pNewTable;
}
if( pTab==0 || pParse->nErr ) goto exit_create_index;
/*
** Find the name of the index. Make sure there is not already another
** index or table with the same name.
*/
if( pName){
Index *pISameName; /* Another index with the same name */
Table *pTSameName; /* A table with same name as the index */
zName = eDbStrNDup(pName->z, pName->n);
if( zName==0 ){
goto exit_create_index;
}
if( (pISameName = eDbFindIndex(db, zName, 0))!=0 ){
eDbErrorMsg(pParse, "index %s already exists", zName);
goto exit_create_index;
}
if( (pTSameName = eDbFindTable(db, zName, 0))!=0 ){
eDbErrorMsg(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);
zName = 0;
eDbSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
if( zName==0 ) goto exit_create_index;
}else{
zName = eDbStrNDup(pName->z, pName->n);
}
if( pList==0 ){
nullId.z = pTab->aCol[pTab->nCol-1].zName;
nullId.n = strlen(nullId.z);
pList = eDbIdListAppend(0, &nullId);
if( pList==0 ) goto exit_create_index;
}
/*
** Allocate the index structure.
*/
pIndex = eDbMalloc( sizeof(Index) + strlen(zName) + 1 +
sizeof(int)*pList->nId );
if( pIndex==0 ){
goto exit_create_index;
}
pIndex->aiColumn = (int*)&pIndex[1];
pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
strcpy(pIndex->zName, zName);
pIndex->pTable = pTab;
pIndex->nColumn = pList->nId;
pIndex->autoIndex = pName==0;
pIndex->unique = onError;
/* Scan the names of the columns of the table to be indexed and
** load the column indices into the Index structure. Report an error
** if any column is not found.
*/
for(i=0; i<pList->nId; i++){
for(j=0; j<pTab->nCol; j++){
if( eDbStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
}
if( j>=pTab->nCol ){
eDbErrorMsg(pParse, "table %s has no column named %s",
pTab->zName, pList->a[i].zName);
eDbFree(pIndex);
goto exit_create_index;
}
pIndex->aiColumn[i] = j;
}
/*
** intert the index to hash table
*/
if( !pParse->explain ){
Index *p;
p = eDbHashInsert(&db->idxHash,
pIndex->zName, strlen(pIndex->zName)+1, pIndex);
if( p ){
eDbFree(pIndex);
goto exit_create_index;
}
}
/*
** add the index to list
*/
pIndex->pNext = pTab->pIndex;
pTab->pIndex = pIndex;
pRes = eDbMalloc(sizeof(ParseResult));
pRes->pIndex = pIndex;
pRes->op = Op_CreateIndex;
pParse->pResult = pRes;
/* Clean up before exiting */
exit_create_index:
eDbIdListDelete(pList);
eDbSrcListDelete(pTable);
eDbFree(zName);
return;
}
/*
** This routine will drop an existing named index. This routine
** implements the DROP INDEX statement.
*/
void eDbDropIndex(Parser *pParse, SrcList *pName){
Index *pIndex;
ParseResult *pRes;
eDb *db = pParse->db;
if( pParse->nErr || eDb_malloc_failed ) return;
pIndex = eDbFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
eDbErrorMsg(pParse, "no such index: %s", pName->a[0].zName);
goto exit_drop_index;
}
if( pIndex->autoIndex ){
eDbErrorMsg(pParse, "index associated with UNIQUE "
"or PRIMARY KEY constraint cannot be dropped", 0);
goto exit_drop_index;
}
/* Delete the in-memory description of this index.
*/
if( !pParse->explain ){
eDbUnlinkIndex(db, pIndex);
}
pRes = eDbMalloc(sizeof(ParseResult));
pRes->pIndex = pIndex;
pRes->op = Op_DropIndex;
pParse->pResult = pRes;
exit_drop_index:
eDbSrcListDelete(pName);
}
/*
** Append a new element to the given IdList. Create a new IdList if
** need be.
**
** A new IdList is returned, or NULL if malloc() fails.
*/
IdList *eDbIdListAppend(IdList *pList, Token *pToken){
if( pList==0 ){
pList = eDbMalloc( sizeof(IdList) );
if( pList==0 ) return 0;
pList->nAlloc = 0;
}
if( pList->nId>=pList->nAlloc ){
struct IdList_item *a;
pList->nAlloc = pList->nAlloc*2 + 5;
a = eDbRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
if( a==0 ){
eDbIdListDelete(pList);
return 0;
}
pList->a = a;
}
memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
if( pToken ){
char **pz = &pList->a[pList->nId].zName;
eDbSetNString(pz, pToken->z, pToken->n, 0);
if( *pz==0 ){
eDbIdListDelete(pList);
return 0;
}else{
eDbDequote(*pz);
}
}
pList->nId++;
return pList;
}
/*
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pToken is NULL.
**
** A new SrcList is returned, or NULL if malloc() fails.
**
** If pDatabase is not null, it means that the table has an optional
** database name prefix. Like this: "database.table". The pDatabase
** points to the table name and the pTable points to the database name.
** The SrcList.a[].zName field is filled with the table name which might
** come from pTable (if pDatabase is NULL) or from pDatabase.
** SrcList.a[].zDatabase is filled with the database name from pTable,
** or with NULL if no database is specified.
**
** In other words, if call like this:
**
** eDbSrcListAppend(A,B,0);
**
** Then B is a table name and the database name is unspecified. If called
** like this:
**
** eDbSrcListAppend(A,B,C);
**
** Then C is the table name and B is the database name.
*/
SrcList *eDbSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
if( pList==0 ){
pList = eDbMalloc( sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
}
if( pList->nSrc>=pList->nAlloc ){
SrcList *pNew;
pList->nAlloc *= 2;
pNew = eDbRealloc(pList,
sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
if( pNew==0 ){
eDbSrcListDelete(pList);
return 0;
}
pList = pNew;
}
memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0]));
if( pDatabase && pDatabase->z==0 ){
pDatabase = 0;
}
if( pDatabase && pTable ){
Token *pTemp = pDatabase;
pDatabase = pTable;
pTable = pTemp;
}
if( pTable ){
char **pz = &pList->a[pList->nSrc].zName;
eDbSetNString(pz, pTable->z, pTable->n, 0);
if( *pz==0 ){
eDbSrcListDelete(pList);
return 0;
}else{
eDbDequote(*pz);
}
}
if( pDatabase ){
char **pz = &pList->a[pList->nSrc].zDatabase;
eDbSetNString(pz, pDatabase->z, pDatabase->n, 0);
if( *pz==0 ){
eDbSrcListDelete(pList);
return 0;
}else{
eDbDequote(*pz);
}
}
pList->a[pList->nSrc].iCursor = -1;
pList->nSrc++;
return pList;
}
/*
** Assign cursors to all tables in a SrcList
*/
void eDbSrcListAssignCursors(Parser *pParse, SrcList *pList){
int i;
for(i=0; i<pList->nSrc; i++){
if( pList->a[i].iCursor<0 ){
pList->a[i].iCursor = pParse->nTab++;
}
}
}
/*
** Add an alias to the last identifier on the given identifier list.
*/
void eDbSrcListAddAlias(SrcList *pList, Token *pToken){
if( pList && pList->nSrc>0 ){
int i = pList->nSrc - 1;
eDbSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0);
eDbDequote(pList->a[i].zAlias);
}
}
/*
** Delete an IdList.
*/
void eDbIdListDelete(IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nId; i++){
eDbFree(pList->a[i].zName);
}
eDbFree(pList->a);
eDbFree(pList);
}
/*
** Return the index in pList of the identifier named zId. Return -1
** if not found.
*/
int eDbIdListIndex(IdList *pList, const char *zName){
int i;
if( pList==0 ) return -1;
for(i=0; i<pList->nId; i++){
if( eDbStrICmp(pList->a[i].zName, zName)==0 ) return i;
}
return -1;
}
/*
** Delete an entire SrcList including all its substructure.
*/
void eDbSrcListDelete(SrcList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nSrc; i++){
eDbFree(pList->a[i].zDatabase);
eDbFree(pList->a[i].zName);
eDbFree(pList->a[i].zAlias);
eDbSelectDelete(pList->a[i].pSelect);
eDbExprDelete(pList->a[i].pOn);
eDbIdListDelete(pList->a[i].pUsing);
}
eDbFree(pList);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -