When doing schema updates, try to convert (incorrect) double-quoted strings
into (SQL-standard) single-quoted strings. FossilOrigin-Name: 0770470488e140fa21cb5097c26d58e21da85544af8b69faced1670bbc6d6089
This commit is contained in:
commit
ed42b98056
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
|||||||
C Tweaks\sto\stest/scanstatus.test\sto\saccount\sfor\sthe\snew\sEQP\sformat.
|
C When\sdoing\sschema\supdates,\stry\sto\sconvert\s(incorrect)\sdouble-quoted\sstrings\ninto\s(SQL-standard)\ssingle-quoted\sstrings.
|
||||||
D 2021-03-23T15:39:02.956
|
D 2021-03-23T16:34:13.598
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -476,7 +476,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
|||||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||||
F src/alter.c 2d631213818b654faaf08755f26e934134c4769757ae9286981401cd6b571081
|
F src/alter.c 842bb68d8fe651a9c997a30ca212f892b9f293a1e6446d748aa2de6e78345f15
|
||||||
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
|
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
|
||||||
F src/attach.c 9cbe761e464025694df8e6f6ee4d9f41432c3a255ca9443ccbb4130eeb87cf72
|
F src/attach.c 9cbe761e464025694df8e6f6ee4d9f41432c3a255ca9443ccbb4130eeb87cf72
|
||||||
F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
|
F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
|
||||||
@ -540,14 +540,14 @@ F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
|
|||||||
F src/prepare.c e21b54489b5c73b06ada15e6fc79b5c6f64b06701924a6ca98944ae59e06256f
|
F src/prepare.c e21b54489b5c73b06ada15e6fc79b5c6f64b06701924a6ca98944ae59e06256f
|
||||||
F src/printf.c 85d3413fa526404f053a2a13150492f94900639fca4c1b2f74a312b5d777a5c3
|
F src/printf.c 85d3413fa526404f053a2a13150492f94900639fca4c1b2f74a312b5d777a5c3
|
||||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||||
F src/resolve.c dd47248c2c914feb0d4428c27d782e2723971d32cfa5536f49306d080df4d45a
|
F src/resolve.c d95db73d3e6a5c689e5f6604b4d2521350e45f2a0f0f84f5a2dc2bfee56580a0
|
||||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||||
F src/select.c fe0a11d7cf2eddd58cf6fc5f65a5faac1eb430102a3f00092673a499bfd4a50e
|
F src/select.c fe0a11d7cf2eddd58cf6fc5f65a5faac1eb430102a3f00092673a499bfd4a50e
|
||||||
F src/shell.c.in dcce260883836c9b58847505fbccce8d5546af925046f7dacd9443e922ece036
|
F src/shell.c.in dcce260883836c9b58847505fbccce8d5546af925046f7dacd9443e922ece036
|
||||||
F src/sqlite.h.in 3426a080ea1f222a73e3bd91e7eacbd30570a0117c03d42c6dde606f33e5e318
|
F src/sqlite.h.in 3426a080ea1f222a73e3bd91e7eacbd30570a0117c03d42c6dde606f33e5e318
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
|
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
|
||||||
F src/sqliteInt.h ff7d50a5426b3c95009878c5999eb4a5f1e6c7b253f5078c3220e721ebce59ee
|
F src/sqliteInt.h 0f6446f61254d21a398900b888f0fe30179b24f87dde42acf94e767a99888c0b
|
||||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||||
@ -646,15 +646,16 @@ F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807
|
|||||||
F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29
|
F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29
|
||||||
F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf
|
F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf
|
||||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||||
F test/alterauth2.test 794ac5cef251819fe364b4fe20f12f86e9c5d68070513c7fd26c17cb244c89af
|
F test/alterauth2.test 381b1ab603c9ef96314a3158528ea17f7964449385a28eeaf8191120b2e24a8d
|
||||||
F test/altercol.test 3456f7cc4196ef8f7d82d245d6e91940eb12bc95c36c91ac4b512f6b5c9a4fa9
|
F test/altercol.test 91f4eb0023d90beee000c06d45f521e07a2444d013b83381c62e88d5f209560f
|
||||||
F test/altercorrupt.test 584d707a80e106952d6382790c8919bcf9f0db678ed3a1c09fd98b7f9d1d3a10
|
F test/altercorrupt.test 584d707a80e106952d6382790c8919bcf9f0db678ed3a1c09fd98b7f9d1d3a10
|
||||||
F test/alterdropcol.test 596623cb8a72d9570bfb8417b0f302810efe007873796f03c17a9e9ff28dade1
|
F test/alterdropcol.test 596623cb8a72d9570bfb8417b0f302810efe007873796f03c17a9e9ff28dade1
|
||||||
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
||||||
F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
|
F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811
|
||||||
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
||||||
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
|
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
|
||||||
F test/altermalloc3.test a3aa6473d8a2086cb568ace146b2520442699bb16970399fb48e9074891ead6d
|
F test/altermalloc3.test 059841a3de6b6780efd9f0b30bf1d9b4443c555f68d39975cbcac2583167b239
|
||||||
|
F test/alterqf.test 67568ad152db8c1187b15633b801242cf960f1beafc51261a3d1725d910baeb2
|
||||||
F test/altertab.test d15362de3d487368e1f64d600fdfc1976033aecf8394c0a88454a5c63b357209
|
F test/altertab.test d15362de3d487368e1f64d600fdfc1976033aecf8394c0a88454a5c63b357209
|
||||||
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
|
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
|
||||||
F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
|
F test/altertab3.test 2b82fa2236a3a91553d53ae5555d8e723c7eec174c41f1fa62ff497355398479
|
||||||
@ -1910,7 +1911,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P d8afde1bf1d41a349a161a293533a9fdf23ff23b8f1bcc323e79e806c5c526f1
|
P 2eb28afd01f43143a9c0cd6cea68f3095f993952d54ee06b781514a7754490cd 531550056c38589c99c9a97b6afdbf8f34ff8d2131d74e9d42af3506e8045064
|
||||||
R 9577b87fee220b0885d79b3942175082
|
R aab22ac2508293d1e9023d896ea6f587
|
||||||
|
T +closed 531550056c38589c99c9a97b6afdbf8f34ff8d2131d74e9d42af3506e8045064
|
||||||
U drh
|
U drh
|
||||||
Z 2236ed07a95fd128b28b01a2b203e820
|
Z 0b217fc8614676d990a942b0e6a0bc1d
|
||||||
|
@ -1 +1 @@
|
|||||||
2eb28afd01f43143a9c0cd6cea68f3095f993952d54ee06b781514a7754490cd
|
0770470488e140fa21cb5097c26d58e21da85544af8b69faced1670bbc6d6089
|
261
src/alter.c
261
src/alter.c
@ -54,7 +54,7 @@ static void renameTestSchema(
|
|||||||
const char *zDb, /* Name of db to verify schema of */
|
const char *zDb, /* Name of db to verify schema of */
|
||||||
int bTemp, /* True if this is the temp db */
|
int bTemp, /* True if this is the temp db */
|
||||||
const char *zWhen, /* "when" part of error message */
|
const char *zWhen, /* "when" part of error message */
|
||||||
const char *zDropColumn /* Name of column being dropped */
|
int bNoDQS /* Do not allow DQS in the schema */
|
||||||
){
|
){
|
||||||
pParse->colNamesSet = 1;
|
pParse->colNamesSet = 1;
|
||||||
sqlite3NestedParse(pParse,
|
sqlite3NestedParse(pParse,
|
||||||
@ -62,9 +62,9 @@ static void renameTestSchema(
|
|||||||
"FROM \"%w\"." DFLT_SCHEMA_TABLE " "
|
"FROM \"%w\"." DFLT_SCHEMA_TABLE " "
|
||||||
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
|
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
|
||||||
" AND sql NOT LIKE 'create virtual%%'"
|
" AND sql NOT LIKE 'create virtual%%'"
|
||||||
" AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %Q)=NULL ",
|
" AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
|
||||||
zDb,
|
zDb,
|
||||||
zDb, bTemp, zWhen, zDropColumn
|
zDb, bTemp, zWhen, bNoDQS
|
||||||
);
|
);
|
||||||
|
|
||||||
if( bTemp==0 ){
|
if( bTemp==0 ){
|
||||||
@ -73,8 +73,32 @@ static void renameTestSchema(
|
|||||||
"FROM temp." DFLT_SCHEMA_TABLE " "
|
"FROM temp." DFLT_SCHEMA_TABLE " "
|
||||||
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
|
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
|
||||||
" AND sql NOT LIKE 'create virtual%%'"
|
" AND sql NOT LIKE 'create virtual%%'"
|
||||||
" AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %Q)=NULL ",
|
" AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",
|
||||||
zDb, zWhen, zDropColumn
|
zDb, zWhen, bNoDQS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate VM code to replace any double-quoted strings (but not double-quoted
|
||||||
|
** identifiers) within the "sql" column of the sqlite_schema table in
|
||||||
|
** database zDb with their single-quoted equivalents. If argument bTemp is
|
||||||
|
** not true, similarly update all SQL statements in the sqlite_schema table
|
||||||
|
** of the temp db.
|
||||||
|
*/
|
||||||
|
static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){
|
||||||
|
sqlite3NestedParse(pParse,
|
||||||
|
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE
|
||||||
|
" SET sql = sqlite_rename_quotefix(%Q, sql)"
|
||||||
|
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
|
||||||
|
" AND sql NOT LIKE 'create virtual%%'" , zDb, zDb
|
||||||
|
);
|
||||||
|
if( bTemp==0 ){
|
||||||
|
sqlite3NestedParse(pParse,
|
||||||
|
"UPDATE temp." DFLT_SCHEMA_TABLE
|
||||||
|
" SET sql = sqlite_rename_quotefix('temp', sql)"
|
||||||
|
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
|
||||||
|
" AND sql NOT LIKE 'create virtual%%'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,7 +261,7 @@ void sqlite3AlterRenameTable(
|
|||||||
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
|
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
|
||||||
"tbl_name = "
|
"tbl_name = "
|
||||||
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
|
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
|
||||||
" sqlite_rename_test(%Q, sql, type, name, 1, 'after rename',0) "
|
" sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
|
||||||
"THEN %Q ELSE tbl_name END "
|
"THEN %Q ELSE tbl_name END "
|
||||||
"WHERE type IN ('view', 'trigger')"
|
"WHERE type IN ('view', 'trigger')"
|
||||||
, zDb, zTabName, zName, zTabName, zDb, zName);
|
, zDb, zTabName, zName, zTabName, zDb, zName);
|
||||||
@ -596,6 +620,10 @@ void sqlite3AlterRenameColumn(
|
|||||||
goto exit_rename_column;
|
goto exit_rename_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure the schema contains no double-quoted strings */
|
||||||
|
renameTestSchema(pParse, zDb, iSchema==1, "", 0);
|
||||||
|
renameFixQuotes(pParse, zDb, iSchema==1);
|
||||||
|
|
||||||
/* Do the rename operation using a recursive UPDATE statement that
|
/* Do the rename operation using a recursive UPDATE statement that
|
||||||
** uses the sqlite_rename_column() SQL function to compute the new
|
** uses the sqlite_rename_column() SQL function to compute the new
|
||||||
** CREATE statement text for the sqlite_schema table.
|
** CREATE statement text for the sqlite_schema table.
|
||||||
@ -625,7 +653,7 @@ void sqlite3AlterRenameColumn(
|
|||||||
|
|
||||||
/* Drop and reload the database schema. */
|
/* Drop and reload the database schema. */
|
||||||
renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
|
renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
|
||||||
renameTestSchema(pParse, zDb, iSchema==1, "after rename", 0);
|
renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);
|
||||||
|
|
||||||
exit_rename_column:
|
exit_rename_column:
|
||||||
sqlite3SrcListDelete(db, pSrc);
|
sqlite3SrcListDelete(db, pSrc);
|
||||||
@ -1049,17 +1077,12 @@ static int renameParseSql(
|
|||||||
const char *zDb, /* Name of schema SQL belongs to */
|
const char *zDb, /* Name of schema SQL belongs to */
|
||||||
sqlite3 *db, /* Database handle */
|
sqlite3 *db, /* Database handle */
|
||||||
const char *zSql, /* SQL to parse */
|
const char *zSql, /* SQL to parse */
|
||||||
int bTemp, /* True if SQL is from temp schema */
|
int bTemp /* True if SQL is from temp schema */
|
||||||
const char *zDropColumn /* Name of column being dropped */
|
|
||||||
){
|
){
|
||||||
int rc;
|
int rc;
|
||||||
char *zErr = 0;
|
char *zErr = 0;
|
||||||
|
|
||||||
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
|
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
|
||||||
if( zDropColumn ){
|
|
||||||
db->init.bDropColumn = 1;
|
|
||||||
db->init.azInit = (char**)&zDropColumn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse the SQL statement passed as the first argument. If no error
|
/* Parse the SQL statement passed as the first argument. If no error
|
||||||
** occurs and the parse does not result in a new table, index or
|
** occurs and the parse does not result in a new table, index or
|
||||||
@ -1092,7 +1115,6 @@ static int renameParseSql(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
db->init.iDb = 0;
|
db->init.iDb = 0;
|
||||||
db->init.bDropColumn = 0;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,47 +1138,75 @@ static int renameEditSql(
|
|||||||
int nSql = sqlite3Strlen30(zSql);
|
int nSql = sqlite3Strlen30(zSql);
|
||||||
sqlite3 *db = sqlite3_context_db_handle(pCtx);
|
sqlite3 *db = sqlite3_context_db_handle(pCtx);
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
char *zQuot;
|
char *zQuot = 0;
|
||||||
char *zOut;
|
char *zOut;
|
||||||
int nQuot;
|
int nQuot;
|
||||||
|
char *zBuf1 = 0;
|
||||||
|
char *zBuf2 = 0;
|
||||||
|
|
||||||
/* Set zQuot to point to a buffer containing a quoted copy of the
|
if( zNew ){
|
||||||
** identifier zNew. If the corresponding identifier in the original
|
/* Set zQuot to point to a buffer containing a quoted copy of the
|
||||||
** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
|
** identifier zNew. If the corresponding identifier in the original
|
||||||
** point to zQuot so that all substitutions are made using the
|
** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
|
||||||
** quoted version of the new column name. */
|
** point to zQuot so that all substitutions are made using the
|
||||||
zQuot = sqlite3MPrintf(db, "\"%w\"", zNew);
|
** quoted version of the new column name. */
|
||||||
if( zQuot==0 ){
|
zQuot = sqlite3MPrintf(db, "\"%w\"", zNew);
|
||||||
return SQLITE_NOMEM;
|
if( zQuot==0 ){
|
||||||
|
return SQLITE_NOMEM;
|
||||||
|
}else{
|
||||||
|
nQuot = sqlite3Strlen30(zQuot);
|
||||||
|
}
|
||||||
|
if( bQuote ){
|
||||||
|
zNew = zQuot;
|
||||||
|
nNew = nQuot;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( nQuot>=nNew );
|
||||||
|
zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
|
||||||
}else{
|
}else{
|
||||||
nQuot = sqlite3Strlen30(zQuot);
|
zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
|
||||||
}
|
if( zOut ){
|
||||||
if( bQuote ){
|
zBuf1 = &zOut[nSql*2+1];
|
||||||
zNew = zQuot;
|
zBuf2 = &zOut[nSql*4+2];
|
||||||
nNew = nQuot;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point pRename->pList contains a list of RenameToken objects
|
/* At this point pRename->pList contains a list of RenameToken objects
|
||||||
** corresponding to all tokens in the input SQL that must be replaced
|
** corresponding to all tokens in the input SQL that must be replaced
|
||||||
** with the new column name. All that remains is to construct and
|
** with the new column name, or with single-quoted versions of themselves.
|
||||||
** return the edited SQL string. */
|
** All that remains is to construct and return the edited SQL string. */
|
||||||
assert( nQuot>=nNew );
|
|
||||||
zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
|
|
||||||
if( zOut ){
|
if( zOut ){
|
||||||
int nOut = nSql;
|
int nOut = nSql;
|
||||||
memcpy(zOut, zSql, nSql);
|
memcpy(zOut, zSql, nSql);
|
||||||
while( pRename->pList ){
|
while( pRename->pList ){
|
||||||
int iOff; /* Offset of token to replace in zOut */
|
int iOff; /* Offset of token to replace in zOut */
|
||||||
RenameToken *pBest = renameColumnTokenNext(pRename);
|
|
||||||
|
|
||||||
u32 nReplace;
|
u32 nReplace;
|
||||||
const char *zReplace;
|
const char *zReplace;
|
||||||
if( sqlite3IsIdChar(*pBest->t.z) ){
|
RenameToken *pBest = renameColumnTokenNext(pRename);
|
||||||
nReplace = nNew;
|
|
||||||
zReplace = zNew;
|
if( zNew ){
|
||||||
|
if( sqlite3IsIdChar(*pBest->t.z) ){
|
||||||
|
nReplace = nNew;
|
||||||
|
zReplace = zNew;
|
||||||
|
}else{
|
||||||
|
nReplace = nQuot;
|
||||||
|
zReplace = zQuot;
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
nReplace = nQuot;
|
/* Dequote the double-quoted token. Then requote it again, this time
|
||||||
zReplace = zQuot;
|
** using single quotes. If the character immediately following the
|
||||||
|
** original token within the input SQL was a single quote ('), then
|
||||||
|
** add another space after the new, single-quoted version of the
|
||||||
|
** token. This is so that (SELECT "string"'alias') maps to
|
||||||
|
** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */
|
||||||
|
memcpy(zBuf1, pBest->t.z, pBest->t.n);
|
||||||
|
zBuf1[pBest->t.n] = 0;
|
||||||
|
sqlite3Dequote(zBuf1);
|
||||||
|
sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
|
||||||
|
pBest->t.z[pBest->t.n]=='\'' ? " " : ""
|
||||||
|
);
|
||||||
|
zReplace = zBuf2;
|
||||||
|
nReplace = sqlite3Strlen30(zReplace);
|
||||||
}
|
}
|
||||||
|
|
||||||
iOff = pBest->t.z - zSql;
|
iOff = pBest->t.z - zSql;
|
||||||
@ -1394,7 +1444,7 @@ static void renameColumnFunc(
|
|||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
db->xAuth = 0;
|
db->xAuth = 0;
|
||||||
#endif
|
#endif
|
||||||
rc = renameParseSql(&sParse, zDb, db, zSql, bTemp, 0);
|
rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);
|
||||||
|
|
||||||
/* Find tokens that need to be replaced. */
|
/* Find tokens that need to be replaced. */
|
||||||
memset(&sWalker, 0, sizeof(Walker));
|
memset(&sWalker, 0, sizeof(Walker));
|
||||||
@ -1598,7 +1648,7 @@ static void renameTableFunc(
|
|||||||
sWalker.xSelectCallback = renameTableSelectCb;
|
sWalker.xSelectCallback = renameTableSelectCb;
|
||||||
sWalker.u.pRename = &sCtx;
|
sWalker.u.pRename = &sCtx;
|
||||||
|
|
||||||
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, 0);
|
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
||||||
@ -1701,6 +1751,119 @@ static void renameTableFunc(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
|
||||||
|
if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){
|
||||||
|
renameTokenFind(pWalker->pParse, pWalker->u.pRename, (void*)pExpr);
|
||||||
|
}
|
||||||
|
return WRC_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The implementation of an SQL scalar function that rewrites DDL statements
|
||||||
|
** so that any string literals that use double-quotes are modified so that
|
||||||
|
** they use single quotes.
|
||||||
|
**
|
||||||
|
** Two arguments must be passed:
|
||||||
|
**
|
||||||
|
** 0: Database name ("main", "temp" etc.).
|
||||||
|
** 1: SQL statement to edit.
|
||||||
|
**
|
||||||
|
** The returned value is the modified SQL statement. For example, given
|
||||||
|
** the database schema:
|
||||||
|
**
|
||||||
|
** CREATE TABLE t1(a, b, c);
|
||||||
|
**
|
||||||
|
** SELECT sqlite_rename_quotefix('main',
|
||||||
|
** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1'
|
||||||
|
** );
|
||||||
|
**
|
||||||
|
** returns the string:
|
||||||
|
**
|
||||||
|
** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
|
||||||
|
*/
|
||||||
|
static void renameQuotefixFunc(
|
||||||
|
sqlite3_context *context,
|
||||||
|
int NotUsed,
|
||||||
|
sqlite3_value **argv
|
||||||
|
){
|
||||||
|
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||||
|
char const *zDb = (const char*)sqlite3_value_text(argv[0]);
|
||||||
|
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
|
sqlite3_xauth xAuth = db->xAuth;
|
||||||
|
db->xAuth = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sqlite3BtreeEnterAll(db);
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(NotUsed);
|
||||||
|
if( zDb && zInput ){
|
||||||
|
int rc;
|
||||||
|
Parse sParse;
|
||||||
|
rc = renameParseSql(&sParse, zDb, db, zInput, 0);
|
||||||
|
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
RenameCtx sCtx;
|
||||||
|
Walker sWalker;
|
||||||
|
|
||||||
|
/* Walker to find tokens that need to be replaced. */
|
||||||
|
memset(&sCtx, 0, sizeof(RenameCtx));
|
||||||
|
memset(&sWalker, 0, sizeof(Walker));
|
||||||
|
sWalker.pParse = &sParse;
|
||||||
|
sWalker.xExprCallback = renameQuotefixExprCb;
|
||||||
|
sWalker.xSelectCallback = renameColumnSelectCb;
|
||||||
|
sWalker.u.pRename = &sCtx;
|
||||||
|
|
||||||
|
if( sParse.pNewTable ){
|
||||||
|
Select *pSelect = sParse.pNewTable->pSelect;
|
||||||
|
if( pSelect ){
|
||||||
|
pSelect->selFlags &= ~SF_View;
|
||||||
|
sParse.rc = SQLITE_OK;
|
||||||
|
sqlite3SelectPrep(&sParse, pSelect, 0);
|
||||||
|
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
sqlite3WalkSelect(&sWalker, pSelect);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
int i;
|
||||||
|
sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
|
||||||
|
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
||||||
|
for(i=0; i<sParse.pNewTable->nCol; i++){
|
||||||
|
sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
||||||
|
}
|
||||||
|
}else if( sParse.pNewIndex ){
|
||||||
|
sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
|
||||||
|
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
|
||||||
|
}else{
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
rc = renameResolveTrigger(&sParse);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
renameWalkTrigger(&sWalker, sParse.pNewTrigger);
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_TRIGGER */
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = renameEditSql(context, &sCtx, zInput, 0, 0);
|
||||||
|
}
|
||||||
|
renameTokenFree(db, sCtx.pList);
|
||||||
|
}
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
sqlite3_result_error_code(context, rc);
|
||||||
|
}
|
||||||
|
renameParseCleanup(&sParse);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
|
db->xAuth = xAuth;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sqlite3BtreeLeaveAll(db);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An SQL user function that checks that there are no parse or symbol
|
** An SQL user function that checks that there are no parse or symbol
|
||||||
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
|
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
|
||||||
@ -1714,7 +1877,7 @@ static void renameTableFunc(
|
|||||||
** 3: Object name.
|
** 3: Object name.
|
||||||
** 4: True if object is from temp schema.
|
** 4: True if object is from temp schema.
|
||||||
** 5: "when" part of error message.
|
** 5: "when" part of error message.
|
||||||
** 6: Name of column being dropped, or NULL.
|
** 6: True to disable the DQS quirk when parsing SQL.
|
||||||
**
|
**
|
||||||
** Unless it finds an error, this function normally returns NULL. However, it
|
** Unless it finds an error, this function normally returns NULL. However, it
|
||||||
** returns integer value 1 if:
|
** returns integer value 1 if:
|
||||||
@ -1733,7 +1896,7 @@ static void renameTableTest(
|
|||||||
int bTemp = sqlite3_value_int(argv[4]);
|
int bTemp = sqlite3_value_int(argv[4]);
|
||||||
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
||||||
char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
|
char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
|
||||||
char const *zDropColumn = (const char*)sqlite3_value_text(argv[6]);
|
int bNoDQS = sqlite3_value_int(argv[6]);
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
sqlite3_xauth xAuth = db->xAuth;
|
sqlite3_xauth xAuth = db->xAuth;
|
||||||
@ -1741,10 +1904,14 @@ static void renameTableTest(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
UNUSED_PARAMETER(NotUsed);
|
UNUSED_PARAMETER(NotUsed);
|
||||||
|
|
||||||
if( zDb && zInput ){
|
if( zDb && zInput ){
|
||||||
int rc;
|
int rc;
|
||||||
Parse sParse;
|
Parse sParse;
|
||||||
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, zDropColumn);
|
int flags = db->flags;
|
||||||
|
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
|
||||||
|
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
|
||||||
|
db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
|
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
|
||||||
NameContext sNC;
|
NameContext sNC;
|
||||||
@ -1812,7 +1979,7 @@ static void dropColumnFunc(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
UNUSED_PARAMETER(NotUsed);
|
UNUSED_PARAMETER(NotUsed);
|
||||||
rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1, 0);
|
rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
|
||||||
if( rc!=SQLITE_OK ) goto drop_column_done;
|
if( rc!=SQLITE_OK ) goto drop_column_done;
|
||||||
pTab = sParse.pNewTable;
|
pTab = sParse.pNewTable;
|
||||||
if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
|
if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
|
||||||
@ -1906,6 +2073,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
|
|||||||
assert( iDb>=0 );
|
assert( iDb>=0 );
|
||||||
zDb = db->aDb[iDb].zDbSName;
|
zDb = db->aDb[iDb].zDbSName;
|
||||||
renameTestSchema(pParse, zDb, iDb==1, "", 0);
|
renameTestSchema(pParse, zDb, iDb==1, "", 0);
|
||||||
|
renameFixQuotes(pParse, zDb, iDb==1);
|
||||||
sqlite3NestedParse(pParse,
|
sqlite3NestedParse(pParse,
|
||||||
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
|
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
|
||||||
"sql = sqlite_drop_column(%d, sql, %d) "
|
"sql = sqlite_drop_column(%d, sql, %d) "
|
||||||
@ -1915,7 +2083,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
|
|||||||
|
|
||||||
/* Drop and reload the database schema. */
|
/* Drop and reload the database schema. */
|
||||||
renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
|
renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
|
||||||
renameTestSchema(pParse, zDb, iDb==1, "after drop column", zCol);
|
renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1);
|
||||||
|
|
||||||
/* Edit rows of table on disk */
|
/* Edit rows of table on disk */
|
||||||
if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
|
if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
|
||||||
@ -1977,6 +2145,7 @@ void sqlite3AlterFunctions(void){
|
|||||||
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
|
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
|
||||||
INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
|
INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
|
||||||
INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
|
INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
|
||||||
|
INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
|
||||||
};
|
};
|
||||||
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
|
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
|
||||||
}
|
}
|
||||||
|
@ -559,7 +559,6 @@ static int lookupName(
|
|||||||
assert( pExpr->op==TK_ID );
|
assert( pExpr->op==TK_ID );
|
||||||
if( ExprHasProperty(pExpr,EP_DblQuoted)
|
if( ExprHasProperty(pExpr,EP_DblQuoted)
|
||||||
&& areDoubleQuotedStringsEnabled(db, pTopNC)
|
&& areDoubleQuotedStringsEnabled(db, pTopNC)
|
||||||
&& (db->init.bDropColumn==0 || sqlite3StrICmp(zCol, db->init.azInit[0])!=0)
|
|
||||||
){
|
){
|
||||||
/* If a double-quoted identifier does not match any known column name,
|
/* If a double-quoted identifier does not match any known column name,
|
||||||
** then treat it as a string.
|
** then treat it as a string.
|
||||||
@ -574,11 +573,6 @@ static int lookupName(
|
|||||||
** Someday, I hope to get rid of this hack. Unfortunately there is
|
** Someday, I hope to get rid of this hack. Unfortunately there is
|
||||||
** a huge amount of legacy SQL that uses it. So for now, we just
|
** a huge amount of legacy SQL that uses it. So for now, we just
|
||||||
** issue a warning.
|
** issue a warning.
|
||||||
**
|
|
||||||
** 2021-03-15: ticket 1c24a659e6d7f3a1
|
|
||||||
** Do not do the ID-to-STRING conversion when doing the schema
|
|
||||||
** sanity check following a DROP COLUMN if the identifer name matches
|
|
||||||
** the name of the column being dropped.
|
|
||||||
*/
|
*/
|
||||||
sqlite3_log(SQLITE_WARNING,
|
sqlite3_log(SQLITE_WARNING,
|
||||||
"double-quoted string literal: \"%w\"", zCol);
|
"double-quoted string literal: \"%w\"", zCol);
|
||||||
|
@ -1533,10 +1533,7 @@ struct sqlite3 {
|
|||||||
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
|
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
|
||||||
unsigned imposterTable : 1; /* Building an imposter table */
|
unsigned imposterTable : 1; /* Building an imposter table */
|
||||||
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
|
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
|
||||||
unsigned bDropColumn : 1; /* Doing schema check after DROP COLUMN */
|
|
||||||
char **azInit; /* "type", "name", and "tbl_name" columns */
|
char **azInit; /* "type", "name", and "tbl_name" columns */
|
||||||
/* or if bDropColumn, then azInit[0] is the */
|
|
||||||
/* name of the column being dropped */
|
|
||||||
} init;
|
} init;
|
||||||
int nVdbeActive; /* Number of VDBEs currently running */
|
int nVdbeActive; /* Number of VDBEs currently running */
|
||||||
int nVdbeRead; /* Number of active VDBEs that read or write */
|
int nVdbeRead; /* Number of active VDBEs that read or write */
|
||||||
|
@ -82,6 +82,7 @@ do_auth_test 1.2 {
|
|||||||
{SQLITE_ALTER_TABLE main t2 {} {}}
|
{SQLITE_ALTER_TABLE main t2 {} {}}
|
||||||
{SQLITE_FUNCTION {} like {} {}}
|
{SQLITE_FUNCTION {} like {} {}}
|
||||||
{SQLITE_FUNCTION {} sqlite_rename_column {} {}}
|
{SQLITE_FUNCTION {} sqlite_rename_column {} {}}
|
||||||
|
{SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
|
||||||
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
|
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
|
||||||
{SQLITE_READ sqlite_master name main {}}
|
{SQLITE_READ sqlite_master name main {}}
|
||||||
{SQLITE_READ sqlite_master sql main {}}
|
{SQLITE_READ sqlite_master sql main {}}
|
||||||
@ -100,6 +101,7 @@ do_auth_test 1.3 {
|
|||||||
} {
|
} {
|
||||||
{SQLITE_FUNCTION {} like {} {}}
|
{SQLITE_FUNCTION {} like {} {}}
|
||||||
{SQLITE_FUNCTION {} sqlite_drop_column {} {}}
|
{SQLITE_FUNCTION {} sqlite_drop_column {} {}}
|
||||||
|
{SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}}
|
||||||
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
|
{SQLITE_FUNCTION {} sqlite_rename_test {} {}}
|
||||||
{SQLITE_READ sqlite_master name main {}}
|
{SQLITE_READ sqlite_master name main {}}
|
||||||
{SQLITE_READ sqlite_master sql main {}}
|
{SQLITE_READ sqlite_master sql main {}}
|
||||||
@ -110,6 +112,7 @@ do_auth_test 1.3 {
|
|||||||
{SQLITE_READ sqlite_temp_master type temp {}}
|
{SQLITE_READ sqlite_temp_master type temp {}}
|
||||||
{SQLITE_SELECT {} {} {} {}}
|
{SQLITE_SELECT {} {} {} {}}
|
||||||
{SQLITE_UPDATE sqlite_master sql main {}}
|
{SQLITE_UPDATE sqlite_master sql main {}}
|
||||||
|
{SQLITE_UPDATE sqlite_temp_master sql temp {}}
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -567,7 +567,7 @@ do_execsql_test 13.1.6 {
|
|||||||
|
|
||||||
do_catchsql_test 13.1.7 {
|
do_catchsql_test 13.1.7 {
|
||||||
ALTER TABLE x1 RENAME COLUMN t TO ttt;
|
ALTER TABLE x1 RENAME COLUMN t TO ttt;
|
||||||
} {1 {database disk image is malformed}}
|
} {1 {error in index x1i: }}
|
||||||
|
|
||||||
do_execsql_test 13.1.8 {
|
do_execsql_test 13.1.8 {
|
||||||
DELETE FROM sqlite_master WHERE name = 'x1i';
|
DELETE FROM sqlite_master WHERE name = 'x1i';
|
||||||
@ -835,5 +835,18 @@ do_execsql_test 22.0 {
|
|||||||
{CREATE TABLE t2(c, othername, extra AS (c + 1))}
|
{CREATE TABLE t2(c, othername, extra AS (c + 1))}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 22.0 {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
CREATE INDEX x1 on t1("c"=b);
|
||||||
|
INSERT INTO t1 VALUES('a', 'a');
|
||||||
|
INSERT INTO t1 VALUES('b', 'b');
|
||||||
|
INSERT INTO t1 VALUES('c', 'c');
|
||||||
|
ALTER TABLE t1 RENAME COLUMN a TO "c";
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
} {ok}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -22,6 +22,14 @@ ifcapable !altertable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
do_execsql_test 1.0 {
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE x1(
|
||||||
|
one, two, three, PRIMARY KEY(one),
|
||||||
|
CHECK (three!="xyz"), CHECK (two!="one")
|
||||||
|
) WITHOUT ROWID;
|
||||||
|
CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
|
||||||
|
CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
|
||||||
|
UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
|
||||||
|
END;
|
||||||
CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
|
CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
|
||||||
INSERT INTO t1 VALUES(1, 2, 3, 4);
|
INSERT INTO t1 VALUES(1, 2, 3, 4);
|
||||||
}
|
}
|
||||||
|
111
test/alterqf.test
Normal file
111
test/alterqf.test
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# 2021 March 16
|
||||||
|
#
|
||||||
|
# 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. This
|
||||||
|
# script focuses on testing internal function sqlite_rename_quotefix().
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set testprefix alterqf
|
||||||
|
|
||||||
|
sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE t1(a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach {tn before after} {
|
||||||
|
1 {CREATE VIEW v1 AS SELECT "a", "b", "notacolumn!", "c" FROM t1}
|
||||||
|
{CREATE VIEW v1 AS SELECT "a", "b", 'notacolumn!', "c" FROM t1}
|
||||||
|
|
||||||
|
2 {CREATE VIEW v1 AS SELECT "a", "b", "not'a'column!", "c" FROM t1}
|
||||||
|
{CREATE VIEW v1 AS SELECT "a", "b", 'not''a''column!', "c" FROM t1}
|
||||||
|
|
||||||
|
3 {CREATE VIEW v1 AS SELECT "a", "b", "not""a""column!", "c" FROM t1}
|
||||||
|
{CREATE VIEW v1 AS SELECT "a", "b", 'not"a"column!', "c" FROM t1}
|
||||||
|
|
||||||
|
4 {CREATE VIEW v1 AS SELECT "val", count("b") FROM t1 GROUP BY "abc"}
|
||||||
|
{CREATE VIEW v1 AS SELECT 'val', count("b") FROM t1 GROUP BY 'abc'}
|
||||||
|
|
||||||
|
5 {CREATE TABLE xyz(a CHECK (a!="str"), b AS (a||"str"))}
|
||||||
|
{CREATE TABLE xyz(a CHECK (a!='str'), b AS (a||'str'))}
|
||||||
|
|
||||||
|
6 {CREATE INDEX i1 ON t1(a || "str", "b", "val")}
|
||||||
|
{CREATE INDEX i1 ON t1(a || 'str', "b", 'val')}
|
||||||
|
|
||||||
|
7 {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT "abcd"; END}
|
||||||
|
{CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT 'abcd'; END}
|
||||||
|
|
||||||
|
8 {CREATE VIEW v1 AS SELECT "string"'alias' FROM t1}
|
||||||
|
{CREATE VIEW v1 AS SELECT 'string' 'alias' FROM t1}
|
||||||
|
|
||||||
|
9 {CREATE INDEX i1 ON t1(a) WHERE "b"="bb"}
|
||||||
|
{CREATE INDEX i1 ON t1(a) WHERE "b"='bb'}
|
||||||
|
|
||||||
|
10 {CREATE TABLE t2(abc, xyz CHECK (xyz != "123"))}
|
||||||
|
{CREATE TABLE t2(abc, xyz CHECK (xyz != '123'))}
|
||||||
|
|
||||||
|
11 {
|
||||||
|
CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
|
||||||
|
SELECT max("str", new."a") FROM t1
|
||||||
|
WHERE group_concat("b", ",") OVER (ORDER BY c||"str");
|
||||||
|
UPDATE t1 SET c= b + "str";
|
||||||
|
DELETE FROM t1 WHERE EXISTS (
|
||||||
|
SELECT 1 FROM t1 AS o WHERE o."a" = "o.a" AND t1.b IN("t1.b")
|
||||||
|
);
|
||||||
|
END;
|
||||||
|
} {
|
||||||
|
CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN
|
||||||
|
SELECT max('str', new."a") FROM t1
|
||||||
|
WHERE group_concat("b", ',') OVER (ORDER BY c||'str');
|
||||||
|
UPDATE t1 SET c= b + 'str';
|
||||||
|
DELETE FROM t1 WHERE EXISTS (
|
||||||
|
SELECT 1 FROM t1 AS o WHERE o."a" = 'o.a' AND t1.b IN('t1.b')
|
||||||
|
);
|
||||||
|
END;
|
||||||
|
}
|
||||||
|
|
||||||
|
} {
|
||||||
|
do_execsql_test 1.$tn {
|
||||||
|
SELECT sqlite_rename_quotefix('main', $before)
|
||||||
|
} [list $after]
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 2.0 {
|
||||||
|
CREATE TABLE x1(
|
||||||
|
one, two, three, PRIMARY KEY(one),
|
||||||
|
CHECK (three!="xyz"), CHECK (two!="one")
|
||||||
|
) WITHOUT ROWID;
|
||||||
|
CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
|
||||||
|
CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
|
||||||
|
UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
|
||||||
|
END;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 2.1 {
|
||||||
|
ALTER TABLE x1 RENAME two TO 'four';
|
||||||
|
SELECT sql FROM sqlite_schema;
|
||||||
|
SELECT sql FROM sqlite_temp_schema;
|
||||||
|
} {{CREATE TABLE x1(
|
||||||
|
one, "four", three, PRIMARY KEY(one),
|
||||||
|
CHECK (three!='xyz'), CHECK ("four"!="one")
|
||||||
|
) WITHOUT ROWID}
|
||||||
|
{CREATE INDEX x1i ON x1(one+"four"+'four') WHERE 'five'}
|
||||||
|
{CREATE TRIGGER AFTER INSERT ON x1 BEGIN
|
||||||
|
UPDATE x1 SET "four"=new.three || 'new' WHERE one=new.one||'';
|
||||||
|
END}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
Loading…
Reference in New Issue
Block a user