/ Check-in [5dbb0734]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Have ALTER TABLE detect and error out for the case where renaming a column changes a the interpretation of a double-quoted identifier in the database schema from an SQL literal to a column reference.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tkt9b78184b-alt
Files: files | file ages | folders
SHA3-256: 5dbb0734aff25e47a58a64abe0e96636cbf8a7a5006df0cfe10af8629af9133c
User & Date: dan 2019-07-02 20:10:02
Wiki:tkt9b78184b-alt
Context
2019-07-08
12:44
Comment improvements. No changes to code. Leaf check-in: b0629132 user: drh tags: tkt9b78184b-alt
2019-07-02
20:10
Have ALTER TABLE detect and error out for the case where renaming a column changes a the interpretation of a double-quoted identifier in the database schema from an SQL literal to a column reference. check-in: 5dbb0734 user: dan tags: tkt9b78184b-alt
2019-06-28
07:08
Use the OP_Sequence opcode for generating unique rowid values for an autoindex on a co-routine implementation of a subquery. check-in: eab42975 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/alter.c.

523
524
525
526
527
528
529


530
531
532
533
534
535
536
...
556
557
558
559
560
561
562






563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590

591
592
593






































594
595
596
597
598
599
600
....
1232
1233
1234
1235
1236
1237
1238



1239
1240
1241
1242
1243
1244
1245
....
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
....
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380




1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
....
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
  Table *pTab;                    /* Table being updated */
  int iCol;                       /* Index of column being renamed */
  char *zOld = 0;                 /* Old column name */
  char *zNew = 0;                 /* New column name */
  const char *zDb;                /* Name of schema containing the table */
  int iSchema;                    /* Index of the schema */
  int bQuote;                     /* True to quote the new name */



  /* Locate the table to be altered */
  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
  if( !pTab ) goto exit_rename_column;

  /* Cannot alter a system table */
  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
................................................................................
    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
  }
  if( iCol==pTab->nCol ){
    sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
    goto exit_rename_column;
  }







  /* Do the rename operation using a recursive UPDATE statement that
  ** uses the sqlite_rename_column() SQL function to compute the new
  ** CREATE statement text for the sqlite_master table.
  */
  sqlite3MayAbort(pParse);
  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
      " AND (type != 'index' OR tbl_name = %Q)"
      " AND sql NOT LIKE 'create virtual%%'",
      zDb, MASTER_NAME, 
      zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
      pTab->zName
  );


  sqlite3NestedParse(pParse, 
      "UPDATE temp.%s SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
      "WHERE type IN ('trigger', 'view')",
      MASTER_NAME, 
      zDb, pTab->zName, iCol, zNew, bQuote
  );


  /* Drop and reload the database schema. */
  renameReloadSchema(pParse, iSchema);
  renameTestSchema(pParse, zDb, iSchema==1);







































 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}
................................................................................
**   2. object:   Name of object
**   3. Database: Database name (e.g. "main")
**   4. Table:    Table name
**   5. iCol:     Index of column to rename
**   6. zNew:     New column name
**   7. bQuote:   Non-zero if the new column name should be quoted.
**   8. bTemp:    True if zSql comes from temp schema



**
** Do a column rename operation on the CREATE statement given in zSql.
** The iCol-th column (left-most is 0) of table zTable is renamed from zCol
** into zNew.  The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
** It is only accessible to SQL created using sqlite3NestedParse().  It is
................................................................................
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  const char *zDb = (const char*)sqlite3_value_text(argv[3]);
  const char *zTable = (const char*)sqlite3_value_text(argv[4]);
  int iCol = sqlite3_value_int(argv[5]);
  const char *zNew = (const char*)sqlite3_value_text(argv[6]);
  int bQuote = sqlite3_value_int(argv[7]);
  int bTemp = sqlite3_value_int(argv[8]);

  const char *zOld;
  int rc;
  Parse sParse;
  Walker sWalker;
  Index *pIdx;
  int i;
  Table *pTab;
................................................................................
          }
          renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld);
          renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld);
        }
      }
    }


    /* Find tokens to edit in UPDATE OF clause */
    if( sParse.pTriggerTab==pTab ){
      renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld);
    }

    /* Find tokens to edit in various expressions and selects */
    renameWalkTrigger(&sWalker, sParse.pNewTrigger);
  }

  assert( rc==SQLITE_OK );




  rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote);

renameColumnFunc_done:
  if( rc!=SQLITE_OK ){
    if( sParse.zErrMsg ){
      renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
    }else{
      sqlite3_result_error_code(context, rc);
    }
  }

  renameParseCleanup(&sParse);
  renameTokenFree(db, sCtx.pList);
................................................................................
}

/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(void){
  static FuncDef aAlterTableFuncs[] = {
    INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_table,  7, renameTableFunc),
    INTERNAL_FUNCTION(sqlite_rename_test,   5, renameTableTest),
  };
  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
#endif  /* SQLITE_ALTER_TABLE */







>
>







 







>
>
>
>
>
>
|
|
|
<







|




|



>
|
|
|
|
|
|
|
|
>


<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







>







 







<










>
>
>
>





|







 







|






523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
....
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
....
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
....
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
....
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
  Table *pTab;                    /* Table being updated */
  int iCol;                       /* Index of column being renamed */
  char *zOld = 0;                 /* Old column name */
  char *zNew = 0;                 /* New column name */
  const char *zDb;                /* Name of schema containing the table */
  int iSchema;                    /* Index of the schema */
  int bQuote;                     /* True to quote the new name */
  Vdbe *v;                        /* VDBE handle */
  int regRefCnt;                  /* Register for number of refs to column */

  /* Locate the table to be altered */
  pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
  if( !pTab ) goto exit_rename_column;

  /* Cannot alter a system table */
  if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
................................................................................
    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
  }
  if( iCol==pTab->nCol ){
    sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
    goto exit_rename_column;
  }

  /* Allocate a register to count the number of rewritten column refs. */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto exit_rename_column;
  regRefCnt = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, OP_Integer, 0, regRefCnt);

  /* Do the rename operation using an UPDATE statement that uses the
  ** sqlite_rename_column() SQL function to compute the new CREATE 
  ** statement text for the sqlite_master table.  */

  sqlite3MayAbort(pParse);
  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d, %d) "
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
      " AND (type != 'index' OR tbl_name = %Q)"
      " AND sql NOT LIKE 'create virtual%%'",
      zDb, MASTER_NAME, 
      zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, regRefCnt,
      pTab->zName
  );

  if( iSchema!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE temp.%s SET "
        "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1, %d)"
        "WHERE type IN ('trigger', 'view')",
        MASTER_NAME, 
        zDb, pTab->zName, iCol, zNew, bQuote, regRefCnt
    );
  }

  /* Drop and reload the database schema. */
  renameReloadSchema(pParse, iSchema);


  /* Now arrange for the sqlite_rename_column() function to be called a
  ** second time on the already rewritten schema. This serves two purposes:
  ** (a) to check that the schema can still be parsed, and (b) to decrement
  ** register regRefCnt once for each reference to the renamed column in the
  ** schema (the calls above incremented regRefCnt once for each such reference
  ** prior to renaming). If register regRefCnt is not left set to 0, then 
  ** renaming the column has left the schema with either more or fewer
  ** references to the column than there was at the beginning of the 
  ** operation. This is an error, so return an error message and SQLITE_ABORT
  ** the statement.  */ 
  sqlite3NestedParse(pParse, 
      "SELECT 1 "
      "FROM \"%w\".%s "
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      "  AND sql NOT LIKE 'create virtual%%'"
      "  AND (type != 'index' OR tbl_name = %Q)"
      "  AND sqlite_rename_column(sql,type,name,%Q,%Q,%d,%Q,%d,%d,%d)=NULL",
      zDb, MASTER_NAME, 
      pTab->zName,
      zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, regRefCnt*-1
  );
  if( iSchema!=1 ){
    sqlite3NestedParse(pParse, 
        "SELECT 1 "
        "FROM temp.%s "
        "WHERE type IN ('trigger', 'view')"
        "  AND sqlite_rename_column(sql,type,name,%Q,%Q,%d,%Q,%d,1,%d)=NULL",
        MASTER_NAME,
        zDb, pTab->zName, iCol, zNew, bQuote, regRefCnt*-1
    );
  }

  sqlite3VdbeAddOp2(v, OP_IfNot, regRefCnt, sqlite3VdbeCurrentAddr(v)+2);
  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
  sqlite3VdbeChangeP4(v, -1, 
      "schema contains ambiguous double-quoted string", P4_STATIC
  );

 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}
................................................................................
**   2. object:   Name of object
**   3. Database: Database name (e.g. "main")
**   4. Table:    Table name
**   5. iCol:     Index of column to rename
**   6. zNew:     New column name
**   7. bQuote:   Non-zero if the new column name should be quoted.
**   8. bTemp:    True if zSql comes from temp schema
**   9. iReg:     Register to increment for each rewritten column ref. Or,
**                if this parameter is negative, -1 times the id of a register
**                to decrement for each rewritten column ref.
**
** Do a column rename operation on the CREATE statement given in zSql.
** The iCol-th column (left-most is 0) of table zTable is renamed from zCol
** into zNew.  The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
** It is only accessible to SQL created using sqlite3NestedParse().  It is
................................................................................
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  const char *zDb = (const char*)sqlite3_value_text(argv[3]);
  const char *zTable = (const char*)sqlite3_value_text(argv[4]);
  int iCol = sqlite3_value_int(argv[5]);
  const char *zNew = (const char*)sqlite3_value_text(argv[6]);
  int bQuote = sqlite3_value_int(argv[7]);
  int bTemp = sqlite3_value_int(argv[8]);
  int regRefCnt = sqlite3_value_int(argv[9]);
  const char *zOld;
  int rc;
  Parse sParse;
  Walker sWalker;
  Index *pIdx;
  int i;
  Table *pTab;
................................................................................
          }
          renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld);
          renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld);
        }
      }
    }


    /* Find tokens to edit in UPDATE OF clause */
    if( sParse.pTriggerTab==pTab ){
      renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld);
    }

    /* Find tokens to edit in various expressions and selects */
    renameWalkTrigger(&sWalker, sParse.pNewTrigger);
  }

  assert( rc==SQLITE_OK );
  if( regRefCnt!=0 ){
    int mul = (regRefCnt<0 ? -1 : 1);
    sqlite3VdbeIncrReg(context, regRefCnt*mul, sCtx.nList*mul);
  }
  rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote);

renameColumnFunc_done:
  if( rc!=SQLITE_OK ){
    if( sParse.zErrMsg ){
      renameColumnParseError(context, regRefCnt<0, argv[1], argv[2], &sParse);
    }else{
      sqlite3_result_error_code(context, rc);
    }
  }

  renameParseCleanup(&sParse);
  renameTokenFree(db, sCtx.pList);
................................................................................
}

/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(void){
  static FuncDef aAlterTableFuncs[] = {
    INTERNAL_FUNCTION(sqlite_rename_column, 10, renameColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_table,  7, renameTableFunc),
    INTERNAL_FUNCTION(sqlite_rename_test,   5, renameTableTest),
  };
  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
#endif  /* SQLITE_ALTER_TABLE */

Changes to src/vdbe.h.

279
280
281
282
283
284
285

286
287
288
289
290
291
292
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);

#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif

int sqlite3NotPureFunc(sqlite3_context*);


/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
** generator.







>







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);

#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif

int sqlite3NotPureFunc(sqlite3_context*);
void sqlite3VdbeIncrReg(sqlite3_context*, int, int);

/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
** generator.

Changes to src/vdbeaux.c.

4905
4906
4907
4908
4909
4910
4911










4912
4913
4914
4915
4916
4917
4918
    sqlite3_result_error(pCtx, 
       "non-deterministic function in index expression or CHECK constraint",
       -1);
    return 0;
  }
  return 1;
}











#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/







>
>
>
>
>
>
>
>
>
>







4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
    sqlite3_result_error(pCtx, 
       "non-deterministic function in index expression or CHECK constraint",
       -1);
    return 0;
  }
  return 1;
}

/*
** Increment the value of register iReg, which is guaranteed to be an 
** integer, in the VM associated with context object pCtx by iVal.
*/
void sqlite3VdbeIncrReg(sqlite3_context *pCtx, int iReg, int iVal){
  Mem *pMem = &pCtx->pVdbe->aMem[iReg];
  assert( pMem->flags==MEM_Int );
  pMem->u.i += iVal;
}

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/

Changes to test/alter.test.

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696

#--------------------------------------------------------------------------
# alter-9.X - Special test: Make sure the sqlite_rename_column() and
# rename_table() functions do not crash when handed bad input.
#
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
do_test alter-9.1 {
  execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)}
} {{}}
foreach {tn sql} {
    1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0,0,0) }
    2 { SELECT SQLITE_RENAME_TABLE(10,20,30,40,50,60,70) }
    3 { SELECT SQLITE_RENAME_TABLE('foo','foo','foo','foo','foo','foo','foo') }
} {
  do_test alter-9.2.$tn {







|







682
683
684
685
686
687
688
689
690
691
692
693
694
695
696

#--------------------------------------------------------------------------
# alter-9.X - Special test: Make sure the sqlite_rename_column() and
# rename_table() functions do not crash when handed bad input.
#
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1
do_test alter-9.1 {
  execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0,0)}
} {{}}
foreach {tn sql} {
    1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0,0,0) }
    2 { SELECT SQLITE_RENAME_TABLE(10,20,30,40,50,60,70) }
    3 { SELECT SQLITE_RENAME_TABLE('foo','foo','foo','foo','foo','foo','foo') }
} {
  do_test alter-9.2.$tn {

Changes to test/alterauth2.test.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

do_auth_test 1.2 {
  ALTER TABLE t2 RENAME a TO aaa;
} {
  {SQLITE_ALTER_TABLE main t2 {} {}} 
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_column {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_test {} {}} 
  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}} 
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

finish_test







<













78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97

do_auth_test 1.2 {
  ALTER TABLE t2 RENAME a TO aaa;
} {
  {SQLITE_ALTER_TABLE main t2 {} {}} 
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_column {} {}} 

  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}} 
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

finish_test

Changes to test/altercol.test.

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
      'CREATE TABLE x1(i INTEGER, t TEXT)',
      'table', 'x1', 'main', 'ddd', -1, 'zzz', 0
  );
} {}

do_execsql_test 14.2 {
  SELECT 
  sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0)
  FROM ddd;
} {{} {} {} {}}
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0

# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default)
# then the sqlite_rename_table() SQL function is not accessible to
# ordinary SQL.
#
do_catchsql_test 14.3 {
  SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0);
} {1 {no such function: sqlite_rename_column}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 15.0 {
  CREATE TABLE xxx(a, b, c);







|









|







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
      'CREATE TABLE x1(i INTEGER, t TEXT)',
      'table', 'x1', 'main', 'ddd', -1, 'zzz', 0
  );
} {}

do_execsql_test 14.2 {
  SELECT 
  sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0, 0)
  FROM ddd;
} {{} {} {} {}}
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0

# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default)
# then the sqlite_rename_table() SQL function is not accessible to
# ordinary SQL.
#
do_catchsql_test 14.3 {
  SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0,0);
} {1 {no such function: sqlite_rename_column}}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 15.0 {
  CREATE TABLE xxx(a, b, c);

Added test/altercol2.test.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 2019 July 3
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing that SQLite can handle a subtle 
# file format change that may be used in the future to implement
# "ALTER TABLE ... RENAME COLUMN ... TO".
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altercol2

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

sqlite3_db_config db DQS_DDL 1

#-------------------------------------------------------------------------
# Check that the ALTER TABLE statement used in bug [9b78184b] is now
# an error (because it effectively transforms a constant string into a 
# column ref).
#
do_execsql_test 1.0 {
  CREATE TABLE t0(c1, c2);
  INSERT INTO t0(c1, c2) VALUES  ('a', 1);
  CREATE INDEX i0 ON t0("C3");
}

do_catchsql_test 1.1 {
  ALTER TABLE t0 RENAME COLUMN c1 TO c3;
} {1 {schema contains ambiguous double-quoted string}}

do_execsql_test 1.2 {
  ALTER TABLE t0 RENAME COLUMN c1 TO c4;
  SELECT DISTINCT * FROM t0;
} {a 1}

finish_test