tursodatabase / libsql-client-ts

TypeScript/JavaScript client API for libSQL
https://docs.turso.tech/sdk/ts/quickstart
MIT License
226 stars 32 forks source link

Panic after enabling embedded replica when using named placeholders #232

Open erkannt opened 3 months ago

erkannt commented 3 months ago
app-1          | thread '<unnamed>' panicked at src/statement.rs:340:62:
app-1          | called `Option::unwrap()` on a `None` value
app-1          | stack backtrace:
app-1          |    0:     0x7f4b06c5b439 - <unknown>
app-1          |    1:     0x7f4b06920400 - <unknown>
app-1          |    2:     0x7f4b06c30e12 - <unknown>
app-1          |    3:     0x7f4b06c5cd9e - <unknown>
app-1          |    4:     0x7f4b06c5c520 - <unknown>
app-1          |    5:     0x7f4b06c5d6e7 - <unknown>
app-1          |    6:     0x7f4b06c5d0b8 - <unknown>
app-1          |    7:     0x7f4b06c5d046 - <unknown>
app-1          |    8:     0x7f4b06c5d033 - <unknown>
app-1          |    9:     0x7f4b06894cb4 - <unknown>
app-1          |   10:     0x7f4b06894e82 - <unknown>
app-1          |   11:     0x7f4b06895245 - <unknown>
app-1          |   12:     0x7f4b069156f0 - <unknown>
app-1          |   13:     0x7f4b068dfa2b - <unknown>
app-1          |   14:           0xc51049 - _ZN6v8impl12_GLOBAL__N_123FunctionCallbackWrapper6InvokeERKN2v820FunctionCallbackInfoINS2_5ValueEEE
app-1          |   15:           0xf57eaf - _ZN2v88internal25FunctionCallbackArguments4CallENS0_15CallHandlerInfoE
app-1          |   16:           0xf5871d - _ZN2v88internal12_GLOBAL__N_119HandleApiCallHelperILb0EEENS0_11MaybeHandleINS0_6ObjectEEEPNS0_7IsolateENS0_6HandleINS0_10HeapObjectEEENS8_INS0_20FunctionTemplateInfoEEENS8_IS4_EEPmi
app-1          |   17:           0xf58be5 - _ZN2v88internal21Builtin_HandleApiCallEiPmPNS0_7IsolateE
app-1          |   18:          0x1963df6 - Builtins_CEntry_Return1_ArgvOnStack_BuiltinExit
const dbClient = libsqlClient.createClient({
  url: conf.EVENT_DB_URL,
  syncUrl: conf.EVENT_DB_SYNC_URL,
  authToken: conf.EVENT_DB_SYNC_TOKEN,
});

Everything works fine when the client has no syncUrl and uses EVENT_DB_SYNC_URL for the url.

Using @libsql/client 0.7

erkannt commented 2 months ago

I was able to narrow this issue down. It seems to occur when I use named placeholders.

This works:

const result = await client.execute({
  sql: "SELECT * FROM users WHERE id = ?",
  args: [1],
});

This panics:

const result = await client.execute({
  sql: "SELECT * FROM users WHERE id = $id",
  args: {id: 23},
});

I've tried :@$ as per the docs. All lead to a panic.

vfssantos commented 1 month ago

I just learned about the same problem here. Also narrowed down to this issue. I also tried using the npm libsql package (which is compatible with better-sqlite3 api), and also have the exact same issue.

As I rely heavily in named arguments, I've created a helper to transform from named to positional arguments. Hope it helps anyone who comes to this issue while it's not fixed:

function convertToPositionalParams({sql, args}) {
    const paramNames = Object.keys(params);
    const positionalParams = [];
    const paramMap = {};

    // Replace named parameters in the SQL with positional parameters (?)
    const transformedSql = sql.replace(/\$([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, paramName) => {
        if (paramNames.includes(paramName)) {
            if (!(paramName in paramMap)) {
                positionalParams.push(params[paramName]);
                paramMap[paramName] = positionalParams.length;  // Track the index of each parameter
            }
            return '?';
        } else {
            throw new Error(`Parameter ${paramName} not found in params object`);
        }
    });

    return {
        sql: transformedSql,
        args: positionalParams
    };
}

In this case, it's using $ as a biding character. But you can change the code to use @ or :as well inside the regex.