Skip to content

Commit 6773b5e

Browse files
committed
fix: escape identifiers with double quotes
1 parent 6184457 commit 6773b5e

File tree

2 files changed

+41
-39
lines changed

2 files changed

+41
-39
lines changed

src/cloudsync.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ char *db_version_build_query (sqlite3 *db) {
360360

361361
// the good news is that the query can be computed in SQLite without the need to do any extra computation from the host language
362362
const char *sql = "WITH table_names AS ("
363-
"SELECT format('%w', name) as tbl_name "
363+
"SELECT format('%q', name) as tbl_name "
364364
"FROM sqlite_master "
365365
"WHERE type='table' "
366366
"AND name LIKE '%_cloudsync'"
@@ -507,12 +507,12 @@ char *table_build_values_sql (sqlite3 *db, cloudsync_table_context *table) {
507507

508508
#if !CLOUDSYNC_DISABLE_ROWIDONLY_TABLES
509509
if (table->rowid_only) {
510-
sql = memory_mprintf("WITH col_names AS (SELECT group_concat(name, ',') AS cols FROM pragma_table_info('%w') WHERE pk=0 ORDER BY cid) SELECT 'SELECT ' || (SELECT cols FROM col_names) || ' FROM %w WHERE rowid=?;'", table->name, table->name);
510+
sql = memory_mprintf("WITH col_names AS (SELECT group_concat('\"' || name || '\"', ',') AS cols FROM pragma_table_info('%q') WHERE pk=0 ORDER BY cid) SELECT 'SELECT ' || (SELECT cols FROM col_names) || ' FROM \"%w\" WHERE rowid=?;'", table->name, table->name);
511511
goto process_process;
512512
}
513513
#endif
514514

515-
sql = cloudsync_memory_mprintf("WITH col_names AS (SELECT group_concat(name, ',') AS cols FROM pragma_table_info('%w') WHERE pk=0 ORDER BY cid), pk_where AS (SELECT group_concat(name, '=? AND ') || '=?' AS pk_clause FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk) SELECT 'SELECT ' || (SELECT cols FROM col_names) || ' FROM %w WHERE ' || (SELECT pk_clause FROM pk_where) || ';'", table->name, table->name, table->name);
515+
sql = cloudsync_memory_mprintf("WITH col_names AS (SELECT group_concat('\"' || name || '\"', ',') AS cols FROM pragma_table_info('%q') WHERE pk=0 ORDER BY cid), pk_where AS (SELECT group_concat('\"' || name || '\"', '=? AND ') || '=?' AS pk_clause FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk) SELECT 'SELECT ' || (SELECT cols FROM col_names) || ' FROM \"%w\" WHERE ' || (SELECT pk_clause FROM pk_where) || ';'", table->name, table->name, table->name);
516516

517517
#if !CLOUDSYNC_DISABLE_ROWIDONLY_TABLES
518518
process_process:
@@ -527,12 +527,12 @@ char *table_build_values_sql (sqlite3 *db, cloudsync_table_context *table) {
527527
char *table_build_mergedelete_sql (sqlite3 *db, cloudsync_table_context *table) {
528528
#if !CLOUDSYNC_DISABLE_ROWIDONLY_TABLES
529529
if (table->rowid_only) {
530-
char *sql = memory_mprintf("DELETE FROM %w WHERE rowid=?;", table->name);
530+
char *sql = memory_mprintf("DELETE FROM \"%w\" WHERE rowid=?;", table->name);
531531
return sql;
532532
}
533533
#endif
534534

535-
char *sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat(name, '=? AND ') || '=?' AS pk_clause FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk) SELECT 'DELETE FROM %w WHERE ' || (SELECT pk_clause FROM pk_where) || ';'", table->name, table->name);
535+
char *sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat('\"' || name || '\"', '=? AND ') || '=?' AS pk_clause FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk) SELECT 'DELETE FROM \"%w\" WHERE ' || (SELECT pk_clause FROM pk_where) || ';'", table->name, table->name);
536536
if (!sql) return NULL;
537537

538538
char *query = dbutils_text_select(db, sql);
@@ -548,20 +548,20 @@ char *table_build_mergeinsert_sql (sqlite3 *db, cloudsync_table_context *table,
548548
if (table->rowid_only) {
549549
if (colname == NULL) {
550550
// INSERT OR IGNORE INTO customers (first_name,last_name) VALUES (?,?);
551-
sql = memory_mprintf("INSERT OR IGNORE INTO %w (rowid) VALUES (?);", table->name);
551+
sql = memory_mprintf("INSERT OR IGNORE INTO \"%w\" (rowid) VALUES (?);", table->name);
552552
} else {
553553
// INSERT INTO customers (first_name,last_name,age) VALUES (?,?,?) ON CONFLICT DO UPDATE SET age=?;
554-
sql = memory_mprintf("INSERT INTO %w (rowid, %w) VALUES (?, ?) ON CONFLICT DO UPDATE SET %w=?;", table->name, colname, colname);
554+
sql = memory_mprintf("INSERT INTO \"%w\" (rowid, \"%w\") VALUES (?, ?) ON CONFLICT DO UPDATE SET \"%w\"=?;", table->name, colname, colname);
555555
}
556556
return sql;
557557
}
558558
#endif
559559

560560
if (colname == NULL) {
561561
// is sentinel insert
562-
sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat(name) AS pk_clause FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk), pk_bind AS (SELECT group_concat('?') AS pk_binding FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk) SELECT 'INSERT OR IGNORE INTO %w (' || (SELECT pk_clause FROM pk_where) || ') VALUES (' || (SELECT pk_binding FROM pk_bind) || ');'", table->name, table->name, table->name);
562+
sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat('\"' || name || '\"') AS pk_clause FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk), pk_bind AS (SELECT group_concat('?') AS pk_binding FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk) SELECT 'INSERT OR IGNORE INTO \"%w\" (' || (SELECT pk_clause FROM pk_where) || ') VALUES (' || (SELECT pk_binding FROM pk_bind) || ');'", table->name, table->name, table->name);
563563
} else {
564-
sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat(name) AS pk_clause FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk), pk_bind AS (SELECT group_concat('?') AS pk_binding FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk) SELECT 'INSERT INTO %w (' || (SELECT pk_clause FROM pk_where) || ',%w) VALUES (' || (SELECT pk_binding FROM pk_bind) || ',?) ON CONFLICT DO UPDATE SET %w=?;'", table->name, table->name, table->name, colname, colname);
564+
sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat('\"' || name || '\"') AS pk_clause FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk), pk_bind AS (SELECT group_concat('?') AS pk_binding FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk) SELECT 'INSERT INTO \"%w\" (' || (SELECT pk_clause FROM pk_where) || ',\"%w\") VALUES (' || (SELECT pk_binding FROM pk_bind) || ',?) ON CONFLICT DO UPDATE SET \"%w\"=?;'", table->name, table->name, table->name, colname, colname);
565565
}
566566
if (!sql) return NULL;
567567

@@ -572,15 +572,17 @@ char *table_build_mergeinsert_sql (sqlite3 *db, cloudsync_table_context *table,
572572
}
573573

574574
char *table_build_value_sql (sqlite3 *db, cloudsync_table_context *table, const char *colname) {
575+
char *colnamequote = dbutils_is_star_table(colname) ? "" : "\"";
576+
575577
#if !CLOUDSYNC_DISABLE_ROWIDONLY_TABLES
576578
if (table->rowid_only) {
577-
char *sql = memory_mprintf("SELECT %w FROM %w WHERE rowid=?;", colname, table->name);
579+
char *sql = memory_mprintf("SELECT %s%w%s FROM \"%w\" WHERE rowid=?;", colnamequote, colname, colnamequote, table->name);
578580
return sql;
579581
}
580582
#endif
581-
583+
582584
// SELECT age FROM customers WHERE first_name=? AND last_name=?;
583-
char *sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat(name, '=? AND ') || '=?' AS pk_clause FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk) SELECT 'SELECT %w FROM %w WHERE ' || (SELECT pk_clause FROM pk_where) || ';'", table->name, colname, table->name);
585+
char *sql = cloudsync_memory_mprintf("WITH pk_where AS (SELECT group_concat('\"' || name || '\"', '=? AND ') || '=?' AS pk_clause FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk) SELECT 'SELECT %s%w%s FROM \"%w\" WHERE ' || (SELECT pk_clause FROM pk_where) || ';'", table->name, colnamequote, colname, colnamequote, table->name);
584586
if (!sql) return NULL;
585587

586588
char *query = dbutils_text_select(db, sql);
@@ -1627,7 +1629,7 @@ int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data,
16271629
// compact meta-table
16281630
// delete entries for removed columns
16291631
char *sql = cloudsync_memory_mprintf("DELETE FROM \"%w_cloudsync\" WHERE \"col_name\" NOT IN ("
1630-
"SELECT name FROM pragma_table_info('%w') UNION SELECT '%s'"
1632+
"SELECT name FROM pragma_table_info('%q') UNION SELECT '%s'"
16311633
")", table->name, table->name, CLOUDSYNC_TOMBSTONE_VALUE);
16321634
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
16331635
cloudsync_memory_free(sql);
@@ -1636,7 +1638,7 @@ int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data,
16361638
goto finalize;
16371639
}
16381640

1639-
sql = cloudsync_memory_mprintf("SELECT group_concat('%w.' || name, ',') FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk;", table->name, table->name);
1641+
sql = cloudsync_memory_mprintf("SELECT group_concat('\"%w\".\"' || name || '\"', ',') FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table->name, table->name);
16401642
if (!sql) {
16411643
rc = SQLITE_NOMEM;
16421644
goto finalize;
@@ -1646,7 +1648,7 @@ int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data,
16461648
cloudsync_memory_free(sql);
16471649

16481650
// delete entries related to rows that no longer exist in the original table, but preserve tombstone
1649-
sql = cloudsync_memory_mprintf("DELETE FROM \"%w_cloudsync\" WHERE (\"col_name\" != '%s' OR (\"col_name\" = '%s' AND col_version %% 2 != 0)) AND NOT EXISTS (SELECT 1 FROM \"%w\" WHERE \"%w_cloudsync\".pk = cloudsync_pk_encode(%w) LIMIT 1);", table->name, CLOUDSYNC_TOMBSTONE_VALUE, CLOUDSYNC_TOMBSTONE_VALUE, table->name, table->name, pkvalues);
1651+
sql = cloudsync_memory_mprintf("DELETE FROM \"%w_cloudsync\" WHERE (\"col_name\" != '%s' OR (\"col_name\" = '%s' AND col_version %% 2 != 0)) AND NOT EXISTS (SELECT 1 FROM \"%w\" WHERE \"%w_cloudsync\".pk = cloudsync_pk_encode(%s) LIMIT 1);", table->name, CLOUDSYNC_TOMBSTONE_VALUE, CLOUDSYNC_TOMBSTONE_VALUE, table->name, table->name, pkvalues);
16501652
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
16511653
if (pkclause) cloudsync_memory_free(pkclause);
16521654
cloudsync_memory_free(sql);
@@ -1674,31 +1676,31 @@ int cloudsync_refill_metatable (sqlite3 *db, cloudsync_context *data, const char
16741676

16751677
sqlite3_stmt *vm = NULL;
16761678
sqlite3_int64 db_version = db_version_next(db, data, CLOUDSYNC_VALUE_NOTSET);
1677-
1678-
char *sql = cloudsync_memory_mprintf("SELECT group_concat(name, ',') FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk;", table_name);
1679-
char *pkclause = dbutils_text_select(db, sql);
1680-
char *pkvalues = (pkclause) ? pkclause : "rowid";
1679+
1680+
char *sql = cloudsync_memory_mprintf("SELECT group_concat('\"' || name || '\"', ',') FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table_name);
1681+
char *pkclause_identifiers = dbutils_text_select(db, sql);
1682+
char *pkvalues_identifiers = (pkclause_identifiers) ? pkclause_identifiers : "rowid";
16811683
cloudsync_memory_free(sql);
16821684

1683-
sql = cloudsync_memory_mprintf("SELECT group_concat('cloudsync_pk_decode(pk, ' || pk || ') AS ' || name, ',') FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk;", table_name);
1685+
sql = cloudsync_memory_mprintf("SELECT group_concat('cloudsync_pk_decode(pk, ' || pk || ') AS ' || '\"' || name || '\"', ',') FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table_name);
16841686
char *pkdecode = dbutils_text_select(db, sql);
16851687
char *pkdecodeval = (pkdecode) ? pkdecode : "cloudsync_pk_decode(pk, 1) AS rowid";
16861688
cloudsync_memory_free(sql);
16871689

1688-
sql = cloudsync_memory_mprintf("SELECT group_concat(name || ' = cloudsync_pk_decode(pk, ' || pk || ')', ' AND ') FROM pragma_table_info('%w') WHERE pk>0 ORDER BY pk;", table_name);
1690+
sql = cloudsync_memory_mprintf("SELECT group_concat('\"' || name || '\"' || ' = cloudsync_pk_decode(pk, ' || pk || ')', ' AND ') FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table_name);
16891691
char *pkonclause = dbutils_text_select(db, sql);
16901692
char *pkonclauseval = (pkonclause) ? pkonclause : "rowid = cloudsync_pk_decode(pk, 1) AS rowid";
16911693
cloudsync_memory_free(sql);
16921694

1693-
sql = cloudsync_memory_mprintf("SELECT cloudsync_insert('%w', %w) FROM (SELECT %w FROM \"%w\" EXCEPT SELECT %s FROM \"%w_cloudsync\");", table_name, pkvalues, pkvalues, table_name, pkdecodeval, table_name);
1695+
sql = cloudsync_memory_mprintf("SELECT cloudsync_insert('%q', %s) FROM (SELECT %s FROM \"%w\" EXCEPT SELECT %s FROM \"%w_cloudsync\");", table_name, pkvalues_identifiers, pkvalues_identifiers, table_name, pkdecodeval, table_name);
16941696
int rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
16951697
cloudsync_memory_free(sql);
16961698
if (rc != SQLITE_OK) goto finalize;
16971699

16981700
// fill missing colums
16991701
// for each non-pk column:
17001702

1701-
sql = cloudsync_memory_mprintf("SELECT cloudsync_pk_encode(%w) FROM \"%w\" LEFT JOIN \"%w_cloudsync\" ON %s AND \"%w_cloudsync\".col_name = ? WHERE \"%w_cloudsync\".db_version IS NULL", pkvalues, table_name, table_name, pkonclauseval, table_name, table_name);
1703+
sql = cloudsync_memory_mprintf("SELECT cloudsync_pk_encode(%s) FROM \"%w\" LEFT JOIN \"%w_cloudsync\" ON %s AND \"%w_cloudsync\".col_name = ? WHERE \"%w_cloudsync\".db_version IS NULL", pkvalues_identifiers, table_name, table_name, pkonclauseval, table_name, table_name);
17021704
rc = sqlite3_prepare(db, sql, -1, &vm, NULL);
17031705
cloudsync_memory_free(sql);
17041706
if (rc != SQLITE_OK) goto finalize;
@@ -1729,7 +1731,7 @@ int cloudsync_refill_metatable (sqlite3 *db, cloudsync_context *data, const char
17291731

17301732
finalize:
17311733
if (rc != SQLITE_OK) DEBUG_ALWAYS("cloudsync_refill_metatable error: %s", sqlite3_errmsg(db));
1732-
if (pkclause) cloudsync_memory_free(pkclause);
1734+
if (pkclause_identifiers) cloudsync_memory_free(pkclause_identifiers);
17331735
if (pkdecode) cloudsync_memory_free(pkdecode);
17341736
if (pkonclause) cloudsync_memory_free(pkonclause);
17351737
if (vm) sqlite3_finalize(vm);

0 commit comments

Comments
 (0)