** function is a no-op.
*/
static void unionDequote(char *z){
- char q = z[0];
-
- /* Set stack variable q to the close-quote character */
- if( q=='[' || q=='\'' || q=='"' || q=='`' ){
- int iIn = 1;
- int iOut = 0;
- if( q=='[' ) q = ']';
- while( z[iIn] ){
- if( z[iIn]==q ){
- if( z[iIn+1]!=q ){
- /* Character iIn was the close quote. */
- iIn++;
- break;
+ if( z ){
+ char q = z[0];
+
+ /* Set stack variable q to the close-quote character */
+ if( q=='[' || q=='\'' || q=='"' || q=='`' ){
+ int iIn = 1;
+ int iOut = 0;
+ if( q=='[' ) q = ']';
+ while( z[iIn] ){
+ if( z[iIn]==q ){
+ if( z[iIn+1]!=q ){
+ /* Character iIn was the close quote. */
+ iIn++;
+ break;
+ }else{
+ /* Character iIn and iIn+1 form an escaped quote character. Skip
+ ** the input cursor past both and copy a single quote character
+ ** to the output buffer. */
+ iIn += 2;
+ z[iOut++] = q;
+ }
}else{
- /* Character iIn and iIn+1 form an escaped quote character. Skip
- ** the input cursor past both and copy a single quote character
- ** to the output buffer. */
- iIn += 2;
- z[iOut++] = q;
+ z[iOut++] = z[iIn++];
}
- }else{
- z[iOut++] = z[iIn++];
}
+ z[iOut] = '\0';
}
- z[iOut] = '\0';
}
}
return pRet;
}
+/*
+** Like unionPrepare(), except prepare the results of vprintf(zFmt, ...)
+** instead of a constant SQL string.
+*/
+static sqlite3_stmt *unionPreparePrintf(
+ int *pRc, /* IN/OUT: Error code */
+ char **pzErr, /* OUT: Error message */
+ sqlite3 *db, /* Database handle */
+ const char *zFmt, /* printf() format string */
+ ... /* Trailing printf args */
+){
+ sqlite3_stmt *pRet = 0;
+ char *zSql;
+ va_list ap;
+ va_start(ap, zFmt);
+
+ zSql = sqlite3_vmprintf(zFmt, ap);
+ if( *pRc==SQLITE_OK ){
+ if( zSql==0 ){
+ *pRc = SQLITE_NOMEM;
+ }else{
+ pRet = unionPrepare(pRc, db, zSql, pzErr);
+ }
+ }
+ sqlite3_free(zSql);
+
+ va_end(ap);
+ return pRet;
+}
+
+
/*
** Call sqlite3_reset() on SQL statement pStmt. If *pRc is set to
** SQLITE_OK when this function is called, then it is set to the
** the results by the "minimum rowid" field. This makes it easier to
** check that there are no rowid range overlaps between source tables
** and that the UnionTab.aSrc[] array is always sorted by rowid. */
- if( zArg ){
- unionDequote(zArg);
- zSql = sqlite3_mprintf("SELECT * FROM (%s) ORDER BY 3", zArg);
- sqlite3_free(zArg);
- zArg = 0;
- }
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }
- pStmt = unionPrepare(&rc, db, zSql, pzErr);
+ unionDequote(zArg);
+ pStmt = unionPreparePrintf(&rc, pzErr, db,
+ "SELECT * FROM (%z) ORDER BY 3", zArg
+ );
/* Allocate the UnionTab structure */
pTab = unionMalloc(&rc, sizeof(UnionTab));
}
unionFinalize(&rc, pStmt);
pStmt = 0;
- sqlite3_free(zArg);
sqlite3_free(zSql);
- zArg = 0;
zSql = 0;
/* Verify that all source tables exist and have compatible schemas. */
}
/* Compose a CREATE TABLE statement and pass it to declare_vtab() */
- if( rc==SQLITE_OK ){
- zSql = sqlite3_mprintf("SELECT "
- "'CREATE TABLE xyz('"
- " || group_concat(quote(name) || ' ' || type, ', ')"
- " || ')',"
- "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
- "FROM pragma_table_info(%Q, ?)",
- pTab->aSrc[0].zTab, pTab->aSrc[0].zDb
- );
- if( zSql==0 ) rc = SQLITE_NOMEM;
- }
- pStmt = unionPrepare(&rc, db, zSql, pzErr);
+ pStmt = unionPreparePrintf(&rc, pzErr, db, "SELECT "
+ "'CREATE TABLE xyz('"
+ " || group_concat(quote(name) || ' ' || type, ', ')"
+ " || ')',"
+ "max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
+ "FROM pragma_table_info(%Q, ?)",
+ pTab->aSrc[0].zTab, pTab->aSrc[0].zDb
+ );
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
const char *zDecl = (const char*)sqlite3_column_text(pStmt, 0);
rc = sqlite3_declare_vtab(db, zDecl);
-C Have\sunionvtab\ssupport\sconstraints\son\sthe\scolumn\sthat\scorresponds\sto\sthe\nINTEGER\sPRIMARY\sKEY\sfield\sof\sthe\sunderlying\ssource\stables\sin\sthe\ssame\sway\sas\nrowid.
-D 2017-07-18T19:51:11.061
+C Improve\sthe\sreadability\sof\sthe\sunionvtab\scode.
+D 2017-07-18T20:03:49.037
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 20850e3e8d4d4791e0531955852d768eb06f24138214870d543abb1a47346fba
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c 2ee97a136cc300fe17c9591015ae2ee4eea2a78458e46dd44550e0a441a091ff
+F ext/misc/unionvtab.c 6f000dda30b9b757d96430b527fa914565db761b052eeff44f4ecc4fb78afb17
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 6c9128e1a53f8cf26de9ef1bc07051f2c94287531edacfcfb69d3cd7590240b3
-R dc8f15610e867937249e25b515a6a200
+P 4a6c416fa025a34116ea30923a673cbb108b251b2676734ec8f603600e38e50e
+R e0c4fc635382665649191367077e776c
U dan
-Z 6262d0cb27792cd399228e6052fa5f80
+Z e8f0cf724e634e649031bed86724d795