📄 alter.c
字号:
** that the table is being renamed to. */ if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); goto exit_rename_table; } if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto exit_rename_table; }#ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ goto exit_rename_table; }#endif#ifndef SQLITE_OMIT_VIRTUALTABLE if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto exit_rename_table; } if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ isVirtualRename = 1; }#endif /* Begin a transaction and code the VerifyCookie for database iDb. ** Then modify the schema cookie (since the ALTER TABLE modifies the ** schema). Open a statement transaction if the table is a virtual ** table. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); sqlite3ChangeCookie(db, v, iDb); /* If this is a virtual table, invoke the xRename() function if ** one is defined. The xRename() callback will modify the names ** of any resources used by the v-table implementation (including other ** SQLite tables) that are identified by the name of the virtual table. */#ifndef SQLITE_OMIT_VIRTUALTABLE if( isVirtualRename ){ sqlite3VdbeOp3(v, OP_String8, 0, 0, zName, 0); sqlite3VdbeOp3(v, OP_VRename, 0, 0, (const char*)pTab->pVtab, P3_VTAB); }#endif /* figure out how many UTF-8 characters are in zName */ zTabName = pTab->zName; nTabName = sqlite3Utf8CharLen(zTabName, -1); /* Modify the sqlite_master table to use the new table name. */ sqlite3NestedParse(pParse, "UPDATE %Q.%s SET "#ifdef SQLITE_OMIT_TRIGGER "sql = sqlite_rename_table(sql, %Q), "#else "sql = CASE " "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" "ELSE sqlite_rename_table(sql, %Q) END, "#endif "tbl_name = %Q, " "name = CASE " "WHEN type='table' THEN %Q " "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " "'sqlite_autoindex_' || %Q || substr(name,%d+18,10) " "ELSE name END " "WHERE tbl_name=%Q AND " "(type='table' OR type='index' OR type='trigger');", zDb, SCHEMA_TABLE(iDb), zName, zName, zName, #ifndef SQLITE_OMIT_TRIGGER zName,#endif zName, nTabName, zTabName );#ifndef SQLITE_OMIT_AUTOINCREMENT /* If the sqlite_sequence table exists in this database, then update ** it with the new table name. */ if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ sqlite3NestedParse(pParse, "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q", zDb, zName, pTab->zName); }#endif#ifndef SQLITE_OMIT_TRIGGER /* If there are TEMP triggers on this table, modify the sqlite_temp_master ** table. Don't do this if the table being ALTERed is itself located in ** the temp database. */ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ sqlite3NestedParse(pParse, "UPDATE sqlite_temp_master SET " "sql = sqlite_rename_trigger(sql, %Q), " "tbl_name = %Q " "WHERE %s;", zName, zName, zWhere); sqliteFree(zWhere); }#endif /* Drop and reload the internal table schema. */ reloadTableSchema(pParse, pTab, zName);exit_rename_table: sqlite3SrcListDelete(pSrc); sqliteFree(zName);}/*** This function is called after an "ALTER TABLE ... ADD" statement** has been parsed. Argument pColDef contains the text of the new** column definition.**** The Table structure pParse->pNewTable was extended to include** the new column during parsing.*/void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ Table *pNew; /* Copy of pParse->pNewTable */ Table *pTab; /* Table being altered */ int iDb; /* Database number */ const char *zDb; /* Database name */ const char *zTab; /* Table name */ char *zCol; /* Null-terminated column definition */ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ if( pParse->nErr ) return; pNew = pParse->pNewTable; assert( pNew ); iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema); zDb = pParse->db->aDb[iDb].zName; zTab = pNew->zName; pCol = &pNew->aCol[pNew->nCol-1]; pDflt = pCol->pDflt; pTab = sqlite3FindTable(pParse->db, zTab, zDb); assert( pTab );#ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ return; }#endif /* If the default value for the new column was specified with a ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. */ if( pDflt && pDflt->op==TK_NULL ){ pDflt = 0; } /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. ** If there is a NOT NULL constraint, then the default value for the ** column must not be NULL. */ if( pCol->isPrimKey ){ sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); return; } if( pNew->pIndex ){ sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); return; } if( pCol->notNull && !pDflt ){ sqlite3ErrorMsg(pParse, "Cannot add a NOT NULL column with default value NULL"); return; } /* Ensure the default expression is something that sqlite3ValueFromExpr() ** can handle (i.e. not CURRENT_TIME etc.) */ if( pDflt ){ sqlite3_value *pVal; if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ /* malloc() has failed */ return; } if( !pVal ){ sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); return; } sqlite3ValueFree(pVal); } /* Modify the CREATE TABLE statement. */ zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){ *zEnd-- = '\0'; } sqlite3NestedParse(pParse, "UPDATE %Q.%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) " "WHERE type = 'table' AND name = %Q", zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); sqliteFree(zCol); } /* If the default value of the new column is NULL, then set the file ** format to 2. If the default value of the new column is not NULL, ** the file format becomes 3. */ sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); /* Reload the schema of the modified table. */ reloadTableSchema(pParse, pTab, pTab->zName);}/*** This function is called by the parser after the table-name in** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument ** pSrc is the full-name of the table being altered.**** This routine makes a (partial) copy of the Table structure** for the table being altered and sets Parse.pNewTable to point** to it. Routines called by the parser as the column definition** is parsed (i.e. sqlite3AddColumn()) add the new Column data to ** the copy. The copy of the Table structure is deleted by tokenize.c ** after parsing is finished.**** Routine sqlite3AlterFinishAddColumn() will be called to complete** coding the "ALTER TABLE ... ADD" statement.*/void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ Table *pNew; Table *pTab; Vdbe *v; int iDb; int i; int nAlloc; /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); if( sqlite3MallocFailed() ) goto exit_begin_add_column; pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_begin_add_column;#ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); goto exit_begin_add_column; }#endif /* Make sure this is not an attempt to ALTER a view. */ if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); goto exit_begin_add_column; } assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. */ pNew = (Table *)sqliteMalloc(sizeof(Table)); if( !pNew ) goto exit_begin_add_column; pParse->pNewTable = pNew; pNew->nRef = 1; pNew->nCol = pTab->nCol; assert( pNew->nCol>0 ); nAlloc = (((pNew->nCol-1)/8)*8)+8; assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc); pNew->zName = sqliteStrDup(pTab->zName); if( !pNew->aCol || !pNew->zName ){ goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; i<pNew->nCol; i++){ Column *pCol = &pNew->aCol[i]; pCol->zName = sqliteStrDup(pCol->zName); pCol->zColl = 0; pCol->zType = 0; pCol->pDflt = 0; } pNew->pSchema = pParse->db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nRef = 1; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); v = sqlite3GetVdbe(pParse); if( !v ) goto exit_begin_add_column; sqlite3ChangeCookie(pParse->db, v, iDb);exit_begin_add_column: sqlite3SrcListDelete(pSrc); return;}#endif /* SQLITE_ALTER_TABLE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -