Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
alter.c3057 linesDownload Raw Back to src
1/*2** 2005 February 153**4** The author disclaims copyright to this source code.  In place of5** a legal notice, here is a blessing:6**7**    May you do good and not evil.8**    May you find forgiveness for yourself and forgive others.9**    May you share freely, never taking more than you give.10**11*************************************************************************12** This file contains C code routines that used to generate VDBE code13** that implements the ALTER TABLE command.14*/15#include "sqliteInt.h"16 17/*18** The code in this file only exists if we are not omitting the19** ALTER TABLE logic from the build.20*/21#ifndef SQLITE_OMIT_ALTERTABLE22 23/*24** Parameter zName is the name of a table that is about to be altered25** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).26** If the table is a system table, this function leaves an error message27** in pParse->zErr (system tables may not be altered) and returns non-zero.28**29** Or, if zName is not a system table, zero is returned.30*/31static int isAlterableTable(Parse *pParse, Table *pTab){32  if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)33#ifndef SQLITE_OMIT_VIRTUALTABLE34   || (pTab->tabFlags & TF_Eponymous)!=035   || ( (pTab->tabFlags & TF_Shadow)!=036        && sqlite3ReadOnlyShadowTables(pParse->db)37   )38#endif39  ){40    sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);41    return 1;42  }43  return 0;44}45 46/*47** Generate code to verify that the schemas of database zDb and, if48** bTemp is not true, database "temp", can still be parsed. This is49** called at the end of the generation of an ALTER TABLE ... RENAME ...50** statement to ensure that the operation has not rendered any schema51** objects unusable.52*/53static void renameTestSchema(54  Parse *pParse,                  /* Parse context */55  const char *zDb,                /* Name of db to verify schema of */56  int bTemp,                      /* True if this is the temp db */57  const char *zWhen,              /* "when" part of error message */58  int bNoDQS                      /* Do not allow DQS in the schema */59){60  pParse->colNamesSet = 1;61  sqlite3NestedParse(pParse,62      "SELECT 1 "63      "FROM \"%w\"." LEGACY_SCHEMA_TABLE " "64      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"65      " AND sql NOT LIKE 'create virtual%%'"66      " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",67      zDb,68      zDb, bTemp, zWhen, bNoDQS69  );70 71  if( bTemp==0 ){72    sqlite3NestedParse(pParse,73        "SELECT 1 "74        "FROM temp." LEGACY_SCHEMA_TABLE " "75        "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"76        " AND sql NOT LIKE 'create virtual%%'"77        " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",78        zDb, zWhen, bNoDQS79    );80  }81}82 83/*84** Generate VM code to replace any double-quoted strings (but not double-quoted85** identifiers) within the "sql" column of the sqlite_schema table in86** database zDb with their single-quoted equivalents. If argument bTemp is87** not true, similarly update all SQL statements in the sqlite_schema table88** of the temp db.89*/90static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){91  sqlite3NestedParse(pParse,92      "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE93      " SET sql = sqlite_rename_quotefix(%Q, sql)"94      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"95      " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb96  );97  if( bTemp==0 ){98    sqlite3NestedParse(pParse,99      "UPDATE temp." LEGACY_SCHEMA_TABLE100      " SET sql = sqlite_rename_quotefix('temp', sql)"101      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"102      " AND sql NOT LIKE 'create virtual%%'"103    );104  }105}106 107/*108** Generate code to reload the schema for database iDb. And, if iDb!=1, for109** the temp database as well.110*/111static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){112  Vdbe *v = pParse->pVdbe;113  if( v ){114    sqlite3ChangeCookie(pParse, iDb);115    sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);116    if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);117  }118}119 120/*121** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"122** command.123*/124void sqlite3AlterRenameTable(125  Parse *pParse,            /* Parser context. */126  SrcList *pSrc,            /* The table to rename. */127  Token *pName              /* The new table name. */128){129  int iDb;                  /* Database that contains the table */130  char *zDb;                /* Name of database iDb */131  Table *pTab;              /* Table being renamed */132  char *zName = 0;          /* NULL-terminated version of pName */133  sqlite3 *db = pParse->db; /* Database connection */134  int nTabName;             /* Number of UTF-8 characters in zTabName */135  const char *zTabName;     /* Original name of the table */136  Vdbe *v;137  VTable *pVTab = 0;        /* Non-zero if this is a v-tab with an xRename() */138 139  if( NEVER(db->mallocFailed) ) goto exit_rename_table;140  assert( pSrc->nSrc==1 );141  assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );142 143  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);144  if( !pTab ) goto exit_rename_table;145  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);146  zDb = db->aDb[iDb].zDbSName;147 148  /* Get a NULL terminated version of the new table name. */149  zName = sqlite3NameFromToken(db, pName);150  if( !zName ) goto exit_rename_table;151 152  /* Check that a table or index named 'zName' does not already exist153  ** in database iDb. If so, this is an error.154  */155  if( sqlite3FindTable(db, zName, zDb)156   || sqlite3FindIndex(db, zName, zDb)157   || sqlite3IsShadowTableOf(db, pTab, zName)158  ){159    sqlite3ErrorMsg(pParse,160        "there is already another table or index with this name: %s", zName);161    goto exit_rename_table;162  }163 164  /* Make sure it is not a system table being altered, or a reserved name165  ** that the table is being renamed to.166  */167  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){168    goto exit_rename_table;169  }170  if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){171    goto exit_rename_table;172  }173 174#ifndef SQLITE_OMIT_VIEW175  if( IsView(pTab) ){176    sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);177    goto exit_rename_table;178  }179#endif180 181#ifndef SQLITE_OMIT_AUTHORIZATION182  /* Invoke the authorization callback. */183  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){184    goto exit_rename_table;185  }186#endif187 188#ifndef SQLITE_OMIT_VIRTUALTABLE189  if( sqlite3ViewGetColumnNames(pParse, pTab) ){190    goto exit_rename_table;191  }192  if( IsVirtual(pTab) ){193    pVTab = sqlite3GetVTable(db, pTab);194    if( pVTab->pVtab->pModule->xRename==0 ){195      pVTab = 0;196    }197  }198#endif199 200  /* Begin a transaction for database iDb. Then modify the schema cookie201  ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(),202  ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the203  ** nested SQL may raise an exception.  */204  v = sqlite3GetVdbe(pParse);205  if( v==0 ){206    goto exit_rename_table;207  }208  sqlite3MayAbort(pParse);209 210  /* figure out how many UTF-8 characters are in zName */211  zTabName = pTab->zName;212  nTabName = sqlite3Utf8CharLen(zTabName, -1);213 214  /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in215  ** the schema to use the new table name.  */216  sqlite3NestedParse(pParse,217      "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "218      "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) "219      "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)"220      "AND   name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"221      , zDb, zDb, zTabName, zName, (iDb==1), zTabName222  );223 224  /* Update the tbl_name and name columns of the sqlite_schema table225  ** as required.  */226  sqlite3NestedParse(pParse,227      "UPDATE %Q." LEGACY_SCHEMA_TABLE " SET "228          "tbl_name = %Q, "229          "name = CASE "230            "WHEN type='table' THEN %Q "231            "WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' "232            "     AND type='index' THEN "233             "'sqlite_autoindex_' || %Q || substr(name,%d+18) "234            "ELSE name END "235      "WHERE tbl_name=%Q COLLATE nocase AND "236          "(type='table' OR type='index' OR type='trigger');",237      zDb,238      zName, zName, zName,239      nTabName, zTabName240  );241 242#ifndef SQLITE_OMIT_AUTOINCREMENT243  /* If the sqlite_sequence table exists in this database, then update244  ** it with the new table name.245  */246  if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){247    sqlite3NestedParse(pParse,248        "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",249        zDb, zName, pTab->zName);250  }251#endif252 253  /* If the table being renamed is not itself part of the temp database,254  ** edit view and trigger definitions within the temp database255  ** as required.  */256  if( iDb!=1 ){257    sqlite3NestedParse(pParse,258        "UPDATE sqlite_temp_schema SET "259            "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "260            "tbl_name = "261              "CASE WHEN tbl_name=%Q COLLATE nocase AND "262              "  sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "263              "THEN %Q ELSE tbl_name END "264            "WHERE type IN ('view', 'trigger')"265        , zDb, zTabName, zName, zTabName, zDb, zName);266  }267 268  /* If this is a virtual table, invoke the xRename() function if269  ** one is defined. The xRename() callback will modify the names270  ** of any resources used by the v-table implementation (including other271  ** SQLite tables) that are identified by the name of the virtual table.272  */273#ifndef SQLITE_OMIT_VIRTUALTABLE274  if( pVTab ){275    int i = ++pParse->nMem;276    sqlite3VdbeLoadString(v, i, zName);277    sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);278  }279#endif280 281  renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);282  renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);283 284exit_rename_table:285  sqlite3SrcListDelete(db, pSrc);286  sqlite3DbFree(db, zName);287}288 289/*290** Write code that will raise an error if the table described by291** zDb and zTab is not empty.292*/293static void sqlite3ErrorIfNotEmpty(294  Parse *pParse,        /* Parsing context */295  const char *zDb,      /* Schema holding the table */296  const char *zTab,     /* Table to check for empty */297  const char *zErr      /* Error message text */298){299  sqlite3NestedParse(pParse,300     "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",301     zErr, zDb, zTab302  );303}304 305/*306** This function is called after an "ALTER TABLE ... ADD" statement307** has been parsed. Argument pColDef contains the text of the new308** column definition.309**310** The Table structure pParse->pNewTable was extended to include311** the new column during parsing.312*/313void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){314  Table *pNew;              /* Copy of pParse->pNewTable */315  Table *pTab;              /* Table being altered */316  int iDb;                  /* Database number */317  const char *zDb;          /* Database name */318  const char *zTab;         /* Table name */319  char *zCol;               /* Null-terminated column definition */320  Column *pCol;             /* The new column */321  Expr *pDflt;              /* Default value for the new column */322  sqlite3 *db;              /* The database connection; */323  Vdbe *v;                  /* The prepared statement under construction */324  int r1;                   /* Temporary registers */325 326  db = pParse->db;327  assert( db->pParse==pParse );328  if( pParse->nErr ) return;329  assert( db->mallocFailed==0 );330  pNew = pParse->pNewTable;331  assert( pNew );332 333  assert( sqlite3BtreeHoldsAllMutexes(db) );334  iDb = sqlite3SchemaToIndex(db, pNew->pSchema);335  zDb = db->aDb[iDb].zDbSName;336  zTab = &pNew->zName[16];  /* Skip the "sqlite_altertab_" prefix on the name */337  pCol = &pNew->aCol[pNew->nCol-1];338  pDflt = sqlite3ColumnExpr(pNew, pCol);339  pTab = sqlite3FindTable(db, zTab, zDb);340  assert( pTab );341 342#ifndef SQLITE_OMIT_AUTHORIZATION343  /* Invoke the authorization callback. */344  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){345    return;346  }347#endif348 349 350  /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.351  ** If there is a NOT NULL constraint, then the default value for the352  ** column must not be NULL.353  */354  if( pCol->colFlags & COLFLAG_PRIMKEY ){355    sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");356    return;357  }358  if( pNew->pIndex ){359    sqlite3ErrorMsg(pParse,360         "Cannot add a UNIQUE column");361    return;362  }363  if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){364    /* If the default value for the new column was specified with a365    ** literal NULL, then set pDflt to 0. This simplifies checking366    ** for an SQL NULL default below.367    */368    assert( pDflt==0 || pDflt->op==TK_SPAN );369    if( pDflt && pDflt->pLeft->op==TK_NULL ){370      pDflt = 0;371    }372    assert( IsOrdinaryTable(pNew) );373    if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){374      sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,375          "Cannot add a REFERENCES column with non-NULL default value");376    }377    if( pCol->notNull && !pDflt ){378      sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,379          "Cannot add a NOT NULL column with default value NULL");380    }381 382 383    /* Ensure the default expression is something that sqlite3ValueFromExpr()384    ** can handle (i.e. not CURRENT_TIME etc.)385    */386    if( pDflt ){387      sqlite3_value *pVal = 0;388      int rc;389      rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);390      assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );391      if( rc!=SQLITE_OK ){392        assert( db->mallocFailed == 1 );393        return;394      }395      if( !pVal ){396        sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,397           "Cannot add a column with non-constant default");398      }399      sqlite3ValueFree(pVal);400    }401  }else if( pCol->colFlags & COLFLAG_STORED ){402    sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column");403  }404 405 406  /* Modify the CREATE TABLE statement. */407  zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);408  if( zCol ){409    char *zEnd = &zCol[pColDef->n-1];410    while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){411      *zEnd-- = '\0';412    }413    /* substr() operations on characters, but addColOffset is in bytes. So we414    ** have to use printf() to translate between these units: */415    assert( IsOrdinaryTable(pTab) );416    assert( IsOrdinaryTable(pNew) );417    sqlite3NestedParse(pParse,418        "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "419          "sql = printf('%%.%ds, ',sql) || %Q"420          " || substr(sql,1+length(printf('%%.%ds',sql))) "421        "WHERE type = 'table' AND name = %Q",422      zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,423      zTab424    );425    sqlite3DbFree(db, zCol);426  }427 428  v = sqlite3GetVdbe(pParse);429  if( v ){430    /* Make sure the schema version is at least 3.  But do not upgrade431    ** from less than 3 to 4, as that will corrupt any preexisting DESC432    ** index.433    */434    r1 = sqlite3GetTempReg(pParse);435    sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);436    sqlite3VdbeUsesBtree(v, iDb);437    sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);438    sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);439    VdbeCoverage(v);440    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);441    sqlite3ReleaseTempReg(pParse, r1);442 443    /* Reload the table definition */444    renameReloadSchema(pParse, iDb, INITFLAG_AlterAdd);445 446    /* Verify that constraints are still satisfied */447    if( pNew->pCheck!=0448     || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)449     || (pTab->tabFlags & TF_Strict)!=0450    ){451      sqlite3NestedParse(pParse,452        "SELECT CASE WHEN quick_check GLOB 'CHECK*'"453        " THEN raise(ABORT,'CHECK constraint failed')"454        " WHEN quick_check GLOB 'non-* value in*'"455        " THEN raise(ABORT,'type mismatch on DEFAULT')"456        " ELSE raise(ABORT,'NOT NULL constraint failed')"457        " END"458        "  FROM pragma_quick_check(%Q,%Q)"459        " WHERE quick_check GLOB 'CHECK*'"460        " OR quick_check GLOB 'NULL*'"461        " OR quick_check GLOB 'non-* value in*'",462        zTab, zDb463      );464    }465  }466}467 468/*469** This function is called by the parser after the table-name in470** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument471** pSrc is the full-name of the table being altered.472**473** This routine makes a (partial) copy of the Table structure474** for the table being altered and sets Parse.pNewTable to point475** to it. Routines called by the parser as the column definition476** is parsed (i.e. sqlite3AddColumn()) add the new Column data to477** the copy. The copy of the Table structure is deleted by tokenize.c478** after parsing is finished.479**480** Routine sqlite3AlterFinishAddColumn() will be called to complete481** coding the "ALTER TABLE ... ADD" statement.482*/483void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){484  Table *pNew;485  Table *pTab;486  int iDb;487  int i;488  int nAlloc;489  sqlite3 *db = pParse->db;490 491  /* Look up the table being altered. */492  assert( pParse->pNewTable==0 );493  assert( sqlite3BtreeHoldsAllMutexes(db) );494  if( NEVER(db->mallocFailed) ) goto exit_begin_add_column;495  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);496  if( !pTab ) goto exit_begin_add_column;497 498#ifndef SQLITE_OMIT_VIRTUALTABLE499  if( IsVirtual(pTab) ){500    sqlite3ErrorMsg(pParse, "virtual tables may not be altered");501    goto exit_begin_add_column;502  }503#endif504 505  /* Make sure this is not an attempt to ALTER a view. */506  if( IsView(pTab) ){507    sqlite3ErrorMsg(pParse, "Cannot add a column to a view");508    goto exit_begin_add_column;509  }510  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){511    goto exit_begin_add_column;512  }513 514  sqlite3MayAbort(pParse);515  assert( IsOrdinaryTable(pTab) );516  assert( pTab->u.tab.addColOffset>0 );517  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);518 519  /* Put a copy of the Table struct in Parse.pNewTable for the520  ** sqlite3AddColumn() function and friends to modify.  But modify521  ** the name by adding an "sqlite_altertab_" prefix.  By adding this522  ** prefix, we insure that the name will not collide with an existing523  ** table because user table are not allowed to have the "sqlite_"524  ** prefix on their name.525  */526  pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));527  if( !pNew ) goto exit_begin_add_column;528  pParse->pNewTable = pNew;529  pNew->nTabRef = 1;530  pNew->nCol = pTab->nCol;531  assert( pNew->nCol>0 );532  nAlloc = (((pNew->nCol-1)/8)*8)+8;533  assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );534  pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc);535  pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);536  if( !pNew->aCol || !pNew->zName ){537    assert( db->mallocFailed );538    goto exit_begin_add_column;539  }540  memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol);541  for(i=0; i<pNew->nCol; i++){542    Column *pCol = &pNew->aCol[i];543    pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);544    pCol->hName = sqlite3StrIHash(pCol->zCnName);545  }546  assert( IsOrdinaryTable(pNew) );547  pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);548  pNew->pSchema = db->aDb[iDb].pSchema;549  pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;550  assert( pNew->nTabRef==1 );551 552exit_begin_add_column:553  sqlite3SrcListDelete(db, pSrc);554  return;555}556 557/*558** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN559** command. This function checks if the table is a view or virtual560** table (columns of views or virtual tables may not be renamed). If so,561** it loads an error message into pParse and returns non-zero.562**563** Or, if pTab is not a view or virtual table, zero is returned.564*/565#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)566static int isRealTable(Parse *pParse, Table *pTab, int iOp){567  const char *zType = 0;568#ifndef SQLITE_OMIT_VIEW569  if( IsView(pTab) ){570    zType = "view";571  }572#endif573#ifndef SQLITE_OMIT_VIRTUALTABLE574  if( IsVirtual(pTab) ){575    zType = "virtual table";576  }577#endif578  if( zType ){579    const char *azMsg[] = {580      "rename columns of", "drop column from", "edit constraints of"581    };582    assert( iOp>=0 && iOp<ArraySize(azMsg) );583    sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"",584        azMsg[iOp], zType, pTab->zName585    );586    return 1;587  }588  return 0;589}590#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */591# define isRealTable(x,y,z) (0)592#endif593 594/*595** Handles the following parser reduction:596**597**  cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew598*/599void sqlite3AlterRenameColumn(600  Parse *pParse,                  /* Parsing context */601  SrcList *pSrc,                  /* Table being altered.  pSrc->nSrc==1 */602  Token *pOld,                    /* Name of column being changed */603  Token *pNew                     /* New column name */604){605  sqlite3 *db = pParse->db;       /* Database connection */606  Table *pTab;                    /* Table being updated */607  int iCol;                       /* Index of column being renamed */608  char *zOld = 0;                 /* Old column name */609  char *zNew = 0;                 /* New column name */610  const char *zDb;                /* Name of schema containing the table */611  int iSchema;                    /* Index of the schema */612  int bQuote;                     /* True to quote the new name */613 614  /* Locate the table to be altered */615  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);616  if( !pTab ) goto exit_rename_column;617 618  /* Cannot alter a system table */619  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;620  if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column;621 622  /* Which schema holds the table to be altered */ 623  iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);624  assert( iSchema>=0 );625  zDb = db->aDb[iSchema].zDbSName;626 627#ifndef SQLITE_OMIT_AUTHORIZATION628  /* Invoke the authorization callback. */629  if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){630    goto exit_rename_column;631  }632#endif633 634  /* Make sure the old name really is a column name in the table to be635  ** altered.  Set iCol to be the index of the column being renamed */636  zOld = sqlite3NameFromToken(db, pOld);637  if( !zOld ) goto exit_rename_column;638  iCol = sqlite3ColumnIndex(pTab, zOld);639  if( iCol<0 ){640    sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);641    goto exit_rename_column;642  }643 644  /* Ensure the schema contains no double-quoted strings */645  renameTestSchema(pParse, zDb, iSchema==1, "", 0);646  renameFixQuotes(pParse, zDb, iSchema==1);647 648  /* Do the rename operation using a recursive UPDATE statement that649  ** uses the sqlite_rename_column() SQL function to compute the new650  ** CREATE statement text for the sqlite_schema table.651  */652  sqlite3MayAbort(pParse);653  zNew = sqlite3NameFromToken(db, pNew);654  if( !zNew ) goto exit_rename_column;655  assert( pNew->n>0 );656  bQuote = sqlite3Isquote(pNew->z[0]);657  sqlite3NestedParse(pParse,658      "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "659      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "660      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "661      " AND (type != 'index' OR tbl_name = %Q)",662      zDb,663      zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,664      pTab->zName665  );666 667  sqlite3NestedParse(pParse,668      "UPDATE temp." LEGACY_SCHEMA_TABLE " SET "669      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "670      "WHERE type IN ('trigger', 'view')",671      zDb, pTab->zName, iCol, zNew, bQuote672  );673 674  /* Drop and reload the database schema. */675  renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);676  renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);677 678 exit_rename_column:679  sqlite3SrcListDelete(db, pSrc);680  sqlite3DbFree(db, zOld);681  sqlite3DbFree(db, zNew);682  return;683}684 685/*686** Each RenameToken object maps an element of the parse tree into687** the token that generated that element.  The parse tree element688** might be one of:689**690**     *  A pointer to an Expr that represents an ID691**     *  The name of a table column in Column.zName692**693** A list of RenameToken objects can be constructed during parsing.694** Each new object is created by sqlite3RenameTokenMap().695** As the parse tree is transformed, the sqlite3RenameTokenRemap()696** routine is used to keep the mapping current.697**698** After the parse finishes, renameTokenFind() routine can be used699** to look up the actual token value that created some element in700** the parse tree.701*/702struct RenameToken {703  const void *p;         /* Parse tree element created by token t */704  Token t;               /* The token that created parse tree element p */705  RenameToken *pNext;    /* Next is a list of all RenameToken objects */706};707 708/*709** The context of an ALTER TABLE RENAME COLUMN operation that gets passed710** down into the Walker.711*/712typedef struct RenameCtx RenameCtx;713struct RenameCtx {714  RenameToken *pList;             /* List of tokens to overwrite */715  int nList;                      /* Number of tokens in pList */716  int iCol;                       /* Index of column being renamed */717  Table *pTab;                    /* Table being ALTERed */718  const char *zOld;               /* Old column name */719};720 721#ifdef SQLITE_DEBUG722/*723** This function is only for debugging. It performs two tasks:724**725**   1. Checks that pointer pPtr does not already appear in the726**      rename-token list.727**728**   2. Dereferences each pointer in the rename-token list.729**730** The second is most effective when debugging under valgrind or731** address-sanitizer or similar. If any of these pointers no longer732** point to valid objects, an exception is raised by the memory-checking733** tool.734**735** The point of this is to prevent comparisons of invalid pointer values.736** Even though this always seems to work, it is undefined according to the737** C standard. Example of undefined comparison:738**739**     sqlite3_free(x);740**     if( x==y ) ...741**742** Technically, as x no longer points into a valid object or to the byte743** following a valid object, it may not be used in comparison operations.744*/745static void renameTokenCheckAll(Parse *pParse, const void *pPtr){746  assert( pParse==pParse->db->pParse );747  assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );748  if( pParse->nErr==0 ){749    const RenameToken *p;750    u32 i = 1;751    for(p=pParse->pRename; p; p=p->pNext){752      if( p->p ){753        assert( p->p!=pPtr );754        i += *(u8*)(p->p) | 1;755      }756    }757    assert( i>0 );758  }759}760#else761# define renameTokenCheckAll(x,y)762#endif763 764/*765** Remember that the parser tree element pPtr was created using766** the token pToken.767**768** In other words, construct a new RenameToken object and add it769** to the list of RenameToken objects currently being built up770** in pParse->pRename.771**772** The pPtr argument is returned so that this routine can be used773** with tail recursion in tokenExpr() routine, for a small performance774** improvement.775*/776const void *sqlite3RenameTokenMap(777  Parse *pParse,778  const void *pPtr,779  const Token *pToken780){781  RenameToken *pNew;782  assert( pPtr || pParse->db->mallocFailed );783  renameTokenCheckAll(pParse, pPtr);784  if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){785    pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));786    if( pNew ){787      pNew->p = pPtr;788      pNew->t = *pToken;789      pNew->pNext = pParse->pRename;790      pParse->pRename = pNew;791    }792  }793 794  return pPtr;795}796 797/*798** It is assumed that there is already a RenameToken object associated799** with parse tree element pFrom. This function remaps the associated token800** to parse tree element pTo.801*/802void sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom){803  RenameToken *p;804  renameTokenCheckAll(pParse, pTo);805  for(p=pParse->pRename; p; p=p->pNext){806    if( p->p==pFrom ){807      p->p = pTo;808      break;809    }810  }811}812 813/*814** Walker callback used by sqlite3RenameExprUnmap().815*/816static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){817  Parse *pParse = pWalker->pParse;818  sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr);819  if( ExprUseYTab(pExpr) ){820    sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab);821  }822  return WRC_Continue;823}824 825/*826** Iterate through the Select objects that are part of WITH clauses attached827** to select statement pSelect.828*/829static void renameWalkWith(Walker *pWalker, Select *pSelect){830  With *pWith = pSelect->pWith;831  if( pWith ){832    Parse *pParse = pWalker->pParse;833    int i;834    With *pCopy = 0;835    assert( pWith->nCte>0 );836    if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){837      /* Push a copy of the With object onto the with-stack. We use a copy838      ** here as the original will be expanded and resolved (flags SF_Expanded839      ** and SF_Resolved) below. And the parser code that uses the with-stack840      ** fails if the Select objects on it have already been expanded and841      ** resolved.  */842      pCopy = sqlite3WithDup(pParse->db, pWith);843      pCopy = sqlite3WithPush(pParse, pCopy, 1);844    }845    for(i=0; i<pWith->nCte; i++){846      Select *p = pWith->a[i].pSelect;847      NameContext sNC;848      memset(&sNC, 0, sizeof(sNC));849      sNC.pParse = pParse;850      if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC);851      if( sNC.pParse->db->mallocFailed ) return;852      sqlite3WalkSelect(pWalker, p);853      sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols);854    }855    if( pCopy && pParse->pWith==pCopy ){856      pParse->pWith = pCopy->pOuter;857    }858  }859}860 861/*862** Unmap all tokens in the IdList object passed as the second argument.863*/864static void unmapColumnIdlistNames(865  Parse *pParse,866  const IdList *pIdList867){868  int ii;869  assert( pIdList!=0 );870  for(ii=0; ii<pIdList->nId; ii++){871    sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName);872  }873}874 875/*876** Walker callback used by sqlite3RenameExprUnmap().877*/878static int renameUnmapSelectCb(Walker *pWalker, Select *p){879  Parse *pParse = pWalker->pParse;880  int i;881  if( pParse->nErr ) return WRC_Abort;882  testcase( p->selFlags & SF_View );883  testcase( p->selFlags & SF_CopyCte );884  if( p->selFlags & (SF_View|SF_CopyCte) ){885    return WRC_Prune;886  }887  if( ALWAYS(p->pEList) ){888    ExprList *pList = p->pEList;889    for(i=0; i<pList->nExpr; i++){890      if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){891        sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);892      }893    }894  }895  if( ALWAYS(p->pSrc) ){  /* Every Select as a SrcList, even if it is empty */896    SrcList *pSrc = p->pSrc;897    for(i=0; i<pSrc->nSrc; i++){898      sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);899      if( pSrc->a[i].fg.isUsing==0 ){900        sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn);901      }else{902        unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing);903      }904    }905  }906 907  renameWalkWith(pWalker, p);908  return WRC_Continue;909}910 911/*912** Remove all nodes that are part of expression pExpr from the rename list.913*/914void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){915  u8 eMode = pParse->eParseMode;916  Walker sWalker;917  memset(&sWalker, 0, sizeof(Walker));918  sWalker.pParse = pParse;919  sWalker.xExprCallback = renameUnmapExprCb;920  sWalker.xSelectCallback = renameUnmapSelectCb;921  pParse->eParseMode = PARSE_MODE_UNMAP;922  sqlite3WalkExpr(&sWalker, pExpr);923  pParse->eParseMode = eMode;924}925 926/*927** Remove all nodes that are part of expression-list pEList from the928** rename list.929*/930void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){931  if( pEList ){932    int i;933    Walker sWalker;934    memset(&sWalker, 0, sizeof(Walker));935    sWalker.pParse = pParse;936    sWalker.xExprCallback = renameUnmapExprCb;937    sqlite3WalkExprList(&sWalker, pEList);938    for(i=0; i<pEList->nExpr; i++){939      if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){940        sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);941      }942    }943  }944}945 946/*947** Free the list of RenameToken objects given in the second argument948*/949static void renameTokenFree(sqlite3 *db, RenameToken *pToken){950  RenameToken *pNext;951  RenameToken *p;952  for(p=pToken; p; p=pNext){953    pNext = p->pNext;954    sqlite3DbFree(db, p);955  }956}957 958/*959** Search the Parse object passed as the first argument for a RenameToken960** object associated with parse tree element pPtr. If found, return a pointer961** to it. Otherwise, return NULL.962**963** If the second argument passed to this function is not NULL and a matching964** RenameToken object is found, remove it from the Parse object and add it to965** the list maintained by the RenameCtx object.966*/967static RenameToken *renameTokenFind(968  Parse *pParse,969  struct RenameCtx *pCtx,970  const void *pPtr971){972  RenameToken **pp;973  if( NEVER(pPtr==0) ){974    return 0;975  }976  for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){977    if( (*pp)->p==pPtr ){978      RenameToken *pToken = *pp;979      if( pCtx ){980        *pp = pToken->pNext;981        pToken->pNext = pCtx->pList;982        pCtx->pList = pToken;983        pCtx->nList++;984      }985      return pToken;986    }987  }988  return 0;989}990 991/*992** This is a Walker select callback. It does nothing. It is only required993** because without a dummy callback, sqlite3WalkExpr() and similar do not994** descend into sub-select statements.995*/996static int renameColumnSelectCb(Walker *pWalker, Select *p){997  if( p->selFlags & (SF_View|SF_CopyCte) ){998    testcase( p->selFlags & SF_View );999    testcase( p->selFlags & SF_CopyCte );1000    return WRC_Prune;1001  }1002  renameWalkWith(pWalker, p);1003  return WRC_Continue;1004}1005 1006/*1007** This is a Walker expression callback.1008**1009** For every TK_COLUMN node in the expression tree, search to see1010** if the column being references is the column being renamed by an1011** ALTER TABLE statement.  If it is, then attach its associated1012** RenameToken object to the list of RenameToken objects being1013** constructed in RenameCtx object at pWalker->u.pRename.1014*/1015static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){1016  RenameCtx *p = pWalker->u.pRename;1017  if( pExpr->op==TK_TRIGGER1018   && pExpr->iColumn==p->iCol1019   && pWalker->pParse->pTriggerTab==p->pTab1020  ){1021    renameTokenFind(pWalker->pParse, p, (void*)pExpr);1022  }else if( pExpr->op==TK_COLUMN1023   && pExpr->iColumn==p->iCol1024   && ALWAYS(ExprUseYTab(pExpr))1025   && p->pTab==pExpr->y.pTab1026  ){1027    renameTokenFind(pWalker->pParse, p, (void*)pExpr);1028  }1029  return WRC_Continue;1030}1031 1032/*1033** The RenameCtx contains a list of tokens that reference a column that1034** is being renamed by an ALTER TABLE statement.  Return the "last"1035** RenameToken in the RenameCtx and remove that RenameToken from the1036** RenameContext.  "Last" means the last RenameToken encountered when1037** the input SQL is parsed from left to right.  Repeated calls to this routine1038** return all column name tokens in the order that they are encountered1039** in the SQL statement.1040*/1041static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){1042  RenameToken *pBest = pCtx->pList;1043  RenameToken *pToken;1044  RenameToken **pp;1045 1046  for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){1047    if( pToken->t.z>pBest->t.z ) pBest = pToken;1048  }1049  for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext);1050  *pp = pBest->pNext;1051 1052  return pBest;1053}1054 1055/*1056** Set the error message of the context passed as the first argument to1057** the result of formatting zFmt using printf() style formatting.1058*/1059static void errorMPrintf(sqlite3_context *pCtx, const char *zFmt, ...){1060  sqlite3 *db = sqlite3_context_db_handle(pCtx);1061  char *zErr = 0;1062  va_list ap;1063  va_start(ap, zFmt);1064  zErr = sqlite3VMPrintf(db, zFmt, ap);1065  va_end(ap);1066  if( zErr ){1067    sqlite3_result_error(pCtx, zErr, -1);1068    sqlite3DbFree(db, zErr);1069  }else{1070    sqlite3_result_error_nomem(pCtx);1071  }1072}1073 1074/*1075** An error occurred while parsing or otherwise processing a database1076** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an1077** ALTER TABLE RENAME COLUMN program. The error message emitted by the1078** sub-routine is currently stored in pParse->zErrMsg. This function1079** adds context to the error message and then stores it in pCtx.1080*/1081static void renameColumnParseError(1082  sqlite3_context *pCtx,1083  const char *zWhen,1084  sqlite3_value *pType,1085  sqlite3_value *pObject,1086  Parse *pParse1087){1088  const char *zT = (const char*)sqlite3_value_text(pType);1089  const char *zN = (const char*)sqlite3_value_text(pObject);1090  char *zErr;1091 1092  zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s",1093      zT, zN, (zWhen[0] ? " " : ""), zWhen,1094      pParse->zErrMsg1095  );1096  sqlite3_result_error(pCtx, zErr, -1);1097  sqlite3DbFree(pParse->db, zErr);1098}1099 1100/*1101** For each name in the the expression-list pEList (i.e. each1102** pEList->a[i].zName) that matches the string in zOld, extract the1103** corresponding rename-token from Parse object pParse and add it1104** to the RenameCtx pCtx.1105*/1106static void renameColumnElistNames(1107  Parse *pParse,1108  RenameCtx *pCtx,1109  const ExprList *pEList,1110  const char *zOld1111){1112  if( pEList ){1113    int i;1114    for(i=0; i<pEList->nExpr; i++){1115      const char *zName = pEList->a[i].zEName;1116      if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME)1117       && ALWAYS(zName!=0)1118       && 0==sqlite3_stricmp(zName, zOld)1119      ){1120        renameTokenFind(pParse, pCtx, (const void*)zName);1121      }1122    }1123  }1124}1125 1126/*1127** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName)1128** that matches the string in zOld, extract the corresponding rename-token1129** from Parse object pParse and add it to the RenameCtx pCtx.1130*/1131static void renameColumnIdlistNames(1132  Parse *pParse,1133  RenameCtx *pCtx,1134  const IdList *pIdList,1135  const char *zOld1136){1137  if( pIdList ){1138    int i;1139    for(i=0; i<pIdList->nId; i++){1140      const char *zName = pIdList->a[i].zName;1141      if( 0==sqlite3_stricmp(zName, zOld) ){1142        renameTokenFind(pParse, pCtx, (const void*)zName);1143      }1144    }1145  }1146}1147 1148 1149/*1150** Parse the SQL statement zSql using Parse object (*p). The Parse object1151** is initialized by this function before it is used.1152*/1153static int renameParseSql(1154  Parse *p,                       /* Memory to use for Parse object */1155  const char *zDb,                /* Name of schema SQL belongs to */1156  sqlite3 *db,                    /* Database handle */1157  const char *zSql,               /* SQL to parse */1158  int bTemp                       /* True if SQL is from temp schema */1159){1160  int rc;1161  u64 flags;1162 1163  sqlite3ParseObjectInit(p, db);1164  if( zSql==0 ){1165    return SQLITE_NOMEM;1166  }1167  if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){1168    return SQLITE_CORRUPT_BKPT;1169  }1170  if( bTemp ){1171    db->init.iDb = 1;1172  }else{1173    int iDb = sqlite3FindDbName(db, zDb);1174    assert( iDb>=0 && iDb<=0xff );1175    db->init.iDb = (u8)iDb;1176  }1177  p->eParseMode = PARSE_MODE_RENAME;1178  p->db = db;1179  p->nQueryLoop = 1;1180  flags = db->flags;1181  testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );1182  db->flags |= SQLITE_Comments;1183  rc = sqlite3RunParser(p, zSql);1184  db->flags = flags;1185  if( db->mallocFailed ) rc = SQLITE_NOMEM;1186  if( rc==SQLITE_OK1187   && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)1188  ){1189    rc = SQLITE_CORRUPT_BKPT;1190  }1191 1192#ifdef SQLITE_DEBUG1193  /* Ensure that all mappings in the Parse.pRename list really do map to1194  ** a part of the input string.  */1195  if( rc==SQLITE_OK ){1196    int nSql = sqlite3Strlen30(zSql);1197    RenameToken *pToken;1198    for(pToken=p->pRename; pToken; pToken=pToken->pNext){1199      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );1200    }

Showing the first 1,200 of 3057 lines. Download the file for the rest.