Skip to content

Commit 84562df

Browse files
sql: rewrite scid string literals to use scid() for index support
When users query with WHERE in_channel='735095x480x1', the string literal is compared directly against the integer SCID column, forcing SQLite to perform a full table scan even when an index exists. Automatically rewrite scid string literals (matching NNNxNNNxNNN format) to use the scid() function before passing the query to SQLite, so '735095x480x1' becomes scid('735095x480x1'). This allows SQLite to use indexes on SCID columns transparently. Queries already using scid() explicitly are detected and left unchanged. Changelog-Fixed: sql plugin now automatically translates short_channel_id string literals to integers for efficient index usage. Fixes: #8941
1 parent 253768a commit 84562df

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

plugins/sql.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,63 @@ static struct command_result *refresh_tables(struct command *cmd,
13221322
return td->refresh(cmd, dbq->tables[0], dbq);
13231323
}
13241324

1325+
/* Check if a string is a valid short_channel_id (NNNxNNNxNNN format) */
1326+
static bool looks_like_scid(const char *str, size_t len)
1327+
{
1328+
struct short_channel_id scid;
1329+
1330+
return short_channel_id_from_str(str, len, &scid);
1331+
}
1332+
1333+
/* Rewrite SQL query to wrap scid string literals with scid() function.
1334+
* This transforms '735095x480x1' into scid('735095x480x1') so that
1335+
* SQLite can use indexes on integer SCID columns. */
1336+
static const char *rewrite_scid_literals(const tal_t *ctx, const char *query)
1337+
{
1338+
char *result = tal_strdup(ctx, "");
1339+
const char *p = query;
1340+
1341+
while (*p) {
1342+
/* Look for single-quoted string literals */
1343+
if (*p == '\'') {
1344+
const char *start = p + 1;
1345+
const char *end = strchr(start, '\'');
1346+
1347+
if (!end) {
1348+
/* Unterminated quote, just copy rest */
1349+
tal_append_fmt(&result, "%s", p);
1350+
break;
1351+
}
1352+
1353+
if (looks_like_scid(start, end - start)) {
1354+
/* Check if already wrapped in scid() by looking
1355+
* back for "scid(" before the quote */
1356+
bool already_wrapped = false;
1357+
if (p - query >= 5) {
1358+
const char *before = p - 5;
1359+
if (strncmp(before, "scid(", 5) == 0)
1360+
already_wrapped = true;
1361+
}
1362+
if (!already_wrapped) {
1363+
tal_append_fmt(&result, "scid('%.*s')",
1364+
(int)(end - start), start);
1365+
p = end + 1;
1366+
continue;
1367+
}
1368+
}
1369+
/* Not a scid or already wrapped: copy quote and content */
1370+
tal_append_fmt(&result, "%.*s",
1371+
(int)(end - p + 1), p);
1372+
p = end + 1;
1373+
} else {
1374+
tal_append_fmt(&result, "%c", *p);
1375+
p++;
1376+
}
1377+
}
1378+
1379+
return result;
1380+
}
1381+
13251382
static struct command_result *json_sql(struct command *cmd,
13261383
const char *buffer,
13271384
const jsmntok_t *params)
@@ -1336,6 +1393,10 @@ static struct command_result *json_sql(struct command *cmd,
13361393
NULL))
13371394
return command_param_failed();
13381395

1396+
/* Rewrite scid string literals to use scid() function so
1397+
* SQLite can use indexes on integer SCID columns. */
1398+
query = rewrite_scid_literals(tmpctx, query);
1399+
13391400
dbq->tables = tal_arr(dbq, struct table_desc *, 0);
13401401
dbq->authfail = NULL;
13411402
dbq->cmd = cmd;

0 commit comments

Comments
 (0)