libsql-js icon indicating copy to clipboard operation
libsql-js copied to clipboard

Named arguments are not recognized (v0.5.20, v0.6.0-pre.18)

Open jsmrcaga opened this issue 5 months ago • 0 comments

Named arguments are not being recognized by the library.

Started tryng this out in Node's REPL but wrote a small test suite to validate.

The integration-tests in the repo clearly show named arguments being used, for example: https://github.com/tursodatabase/libsql-js/blob/f41d1babc528e5c4e5803d50184c0103f80bd435/integration-tests/tests/async.test.js#L101 But I have not been able to replicate this behaviour.

This is an example query:

SELECT * FROM plep LIMIT $limit

and running it with

// Synchronous DB
const statement = db.prepare(query);
const result = statement.get({ limit: 5 });

Fails with

 SqliteError: Hrana: 'cursor error: 'error at step 0: (error code: ARGS_INVALID) 'Arguments do not match SQL parameters: value for parameter $limit not found'''

This is the result summary of the entire test suite (ran using npx mocha ./libsql-test-args.js), and formatted as diff to show colors in GitHub:

  Params test
    Synchronous test
      Named args
-        1) .get(): SELECT * FROM plep LIMIT $limit
-        2) .run(): SELECT * FROM plep LIMIT $limit
-        3) .all(): SELECT * FROM plep LIMIT $limit
-        4) .get(): SELECT * FROM plep WHERE quantity = $q
-        5) .run(): SELECT * FROM plep WHERE quantity = $q
-        6) .all(): SELECT * FROM plep WHERE quantity = $q
-        7) .get(): SELECT * FROM plep WHERE quantity = $quantity
-        8) .run(): SELECT * FROM plep WHERE quantity = $quantity
-        9) .all(): SELECT * FROM plep WHERE quantity = $quantity
      Positional args
+        ✔ .get(): SELECT * FROM plep LIMIT ?
+        ✔ .run(): SELECT * FROM plep LIMIT ?
+        ✔ .all(): SELECT * FROM plep LIMIT ?
+        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .all(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .all(): SELECT * FROM plep WHERE quantity = ?


    Asynchronous test
      Named
-        10) .get(): SELECT * FROM plep LIMIT $limit
-        11) .run(): SELECT * FROM plep LIMIT $limit
-        12) .all(): SELECT * FROM plep LIMIT $limit
-        13) .get(): SELECT * FROM plep WHERE quantity = $q
-        14) .run(): SELECT * FROM plep WHERE quantity = $q
-        15) .all(): SELECT * FROM plep WHERE quantity = $q
-        16) .get(): SELECT * FROM plep WHERE quantity = $quantity
-        17) .run(): SELECT * FROM plep WHERE quantity = $quantity
-        18) .all(): SELECT * FROM plep WHERE quantity = $quantity
      Positional
+        ✔ .get(): SELECT * FROM plep LIMIT ?
+        ✔ .run(): SELECT * FROM plep LIMIT ?
+        ✔ .all(): SELECT * FROM plep LIMIT ?
+        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .all(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
+        ✔ .all(): SELECT * FROM plep WHERE quantity = ?

Here is the full test suite

Test suite
const SyncDB = require('libsql');
// Change if using v0.5.20 or v0.6.0
const { Database: AsyncDB } = require('libsql/promise');
// const AsyncDB = require('libsql/promise');


const named_queries = [
	['SELECT * FROM plep LIMIT $limit', { limit: 5 }],
	['SELECT * FROM plep WHERE quantity = $q', { q: 5 }],
	['SELECT * FROM plep WHERE quantity = $quantity', { quantity: 5 }]
];

const positional_queries = [
	['SELECT * FROM plep LIMIT ?', [5]],
	['SELECT * FROM plep WHERE quantity = ?', [5]],
	['SELECT * FROM plep WHERE quantity = ?', [5]]
];

describe('Params test', () => {
	let syncDB;
	let asyncDB;

	beforeEach(() => {
		syncDB = new SyncDB('http://localhost:8080');
		asyncDB = new AsyncDB('http://localhost:8080');
	});

	describe('Synchronous test', () => {
		describe('Named args', () => {
			for(const [query, named_args] of named_queries) {
				it(`.get(): ${query}`, () => {
					const statement = syncDB.prepare(query);
					const result = statement.get(named_args);
				});

				it(`.run(): ${query}`, () => {
					const statement = syncDB.prepare(query);
					const result = statement.run(named_args);
				});

				it(`.all(): ${query}`, () => {
					const statement = syncDB.prepare(query);
					const result = statement.all(named_args);
				});
			}
		});

		describe('Positional args', () => {
			for(const [query, positional_args] of positional_queries) {
				it(`.get(): ${query}`, () => {
					const statement = syncDB.prepare(query);
					const result = statement.get(...positional_args);
				});

				it(`.run(): ${query}`, () => {
					const statement = syncDB.prepare(query);
					const result = statement.run(...positional_args);
				});

				it(`.all(): ${query}`, () => {
					const statement = syncDB.prepare(query);
					const result = statement.all(...positional_args);
				});
			};
		});
	});

	describe('Asynchronous test', () => {
		describe('Named', () => {
			for(const [query, named_args] of named_queries) {
				it(`.get(): ${query}`, async () => {
					const statement = await asyncDB.prepare(query);
					const result = await statement.get(named_args);
				});

				it(`.run(): ${query}`, async () => {
					const statement = await asyncDB.prepare(query);
					const result = await statement.run(named_args);
				});

				it(`.all(): ${query}`, async () => {
					const statement = await asyncDB.prepare(query);
					const result = await statement.all(named_args);
				});
			}
		});

		describe('Positional', () => {
			for(const [query, positional_args] of positional_queries) {
				it(`.get(): ${query}`, async () => {
					const statement = await asyncDB.prepare(query);
					const result = await statement.get(...positional_args);
				});

				it(`.run(): ${query}`, async () => {
					const statement = await asyncDB.prepare(query);
					const result = await statement.run(...positional_args);
				});

				it(`.all(): ${query}`, async () => {
					const statement = await asyncDB.prepare(query);
					const result = await statement.all(...positional_args);
				});
			};
		});
	});
});

As well as the full output:


  Params test
    Synchronous test
      Named args
        1) .get(): SELECT * FROM plep LIMIT $limit
        2) .run(): SELECT * FROM plep LIMIT $limit
        3) .all(): SELECT * FROM plep LIMIT $limit
        4) .get(): SELECT * FROM plep WHERE quantity = $q
        5) .run(): SELECT * FROM plep WHERE quantity = $q
        6) .all(): SELECT * FROM plep WHERE quantity = $q
        7) .get(): SELECT * FROM plep WHERE quantity = $quantity
        8) .run(): SELECT * FROM plep WHERE quantity = $quantity
        9) .all(): SELECT * FROM plep WHERE quantity = $quantity
      Positional args
        ✔ .get(): SELECT * FROM plep LIMIT ?
        ✔ .run(): SELECT * FROM plep LIMIT ?
        ✔ .all(): SELECT * FROM plep LIMIT ?
        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
        ✔ .all(): SELECT * FROM plep WHERE quantity = ?
        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
        ✔ .all(): SELECT * FROM plep WHERE quantity = ?
    Asynchronous test
      Named
        10) .get(): SELECT * FROM plep LIMIT $limit
        11) .run(): SELECT * FROM plep LIMIT $limit
        12) .all(): SELECT * FROM plep LIMIT $limit
        13) .get(): SELECT * FROM plep WHERE quantity = $q
        14) .run(): SELECT * FROM plep WHERE quantity = $q
        15) .all(): SELECT * FROM plep WHERE quantity = $q
        16) .get(): SELECT * FROM plep WHERE quantity = $quantity
        17) .run(): SELECT * FROM plep WHERE quantity = $quantity
        18) .all(): SELECT * FROM plep WHERE quantity = $quantity
      Positional
        ✔ .get(): SELECT * FROM plep LIMIT ?
        ✔ .run(): SELECT * FROM plep LIMIT ?
        ✔ .all(): SELECT * FROM plep LIMIT ?
        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
        ✔ .all(): SELECT * FROM plep WHERE quantity = ?
        ✔ .get(): SELECT * FROM plep WHERE quantity = ?
        ✔ .run(): SELECT * FROM plep WHERE quantity = ?
        ✔ .all(): SELECT * FROM plep WHERE quantity = ?


  18 passing (9s)
  18 failing

  1) Params test
       Synchronous test
         Named args
           .get(): SELECT * FROM plep LIMIT $limit:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $limit not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.get (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:281:13)
      at Context.<anonymous> (libsql-test-args.js:30:31)
      at process.processImmediate (node:internal/timers:511:21)

  2) Params test
       Synchronous test
         Named args
           .run(): SELECT * FROM plep LIMIT $limit:
     SqliteError: Hrana: `stream error: `Error { message: "Arguments do not match SQL parameters: value for parameter $limit not found", code: "ARGS_INVALID" }``
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.run (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:268:13)
      at Context.<anonymous> (libsql-test-args.js:35:31)
      at process.processImmediate (node:internal/timers:511:21)

  3) Params test
       Synchronous test
         Named args
           .all(): SELECT * FROM plep LIMIT $limit:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $limit not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.all (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:321:13)
      at Context.<anonymous> (libsql-test-args.js:40:31)
      at process.processImmediate (node:internal/timers:511:21)

  4) Params test
       Synchronous test
         Named args
           .get(): SELECT * FROM plep WHERE quantity = $q:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $q not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.get (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:281:13)
      at Context.<anonymous> (libsql-test-args.js:30:31)
      at process.processImmediate (node:internal/timers:511:21)

  5) Params test
       Synchronous test
         Named args
           .run(): SELECT * FROM plep WHERE quantity = $q:
     SqliteError: Hrana: `stream error: `Error { message: "Arguments do not match SQL parameters: value for parameter $q not found", code: "ARGS_INVALID" }``
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.run (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:268:13)
      at Context.<anonymous> (libsql-test-args.js:35:31)
      at process.processImmediate (node:internal/timers:511:21)

  6) Params test
       Synchronous test
         Named args
           .all(): SELECT * FROM plep WHERE quantity = $q:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $q not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.all (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:321:13)
      at Context.<anonymous> (libsql-test-args.js:40:31)
      at process.processImmediate (node:internal/timers:511:21)

  7) Params test
       Synchronous test
         Named args
           .get(): SELECT * FROM plep WHERE quantity = $quantity:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $quantity not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.get (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:281:13)
      at Context.<anonymous> (libsql-test-args.js:30:31)
      at process.processImmediate (node:internal/timers:511:21)

  8) Params test
       Synchronous test
         Named args
           .run(): SELECT * FROM plep WHERE quantity = $quantity:
     SqliteError: Hrana: `stream error: `Error { message: "Arguments do not match SQL parameters: value for parameter $quantity not found", code: "ARGS_INVALID" }``
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.run (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:268:13)
      at Context.<anonymous> (libsql-test-args.js:35:31)
      at process.processImmediate (node:internal/timers:511:21)

  9) Params test
       Synchronous test
         Named args
           .all(): SELECT * FROM plep WHERE quantity = $quantity:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $quantity not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.all (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:321:13)
      at Context.<anonymous> (libsql-test-args.js:40:31)
      at process.processImmediate (node:internal/timers:511:21)

  10) Params test
       Asynchronous test
         Named
           .get(): SELECT * FROM plep LIMIT $limit:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $limit not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.get (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:281:13)
      at Context.<anonymous> (libsql-test-args.js:70:37)

  11) Params test
       Asynchronous test
         Named
           .run(): SELECT * FROM plep LIMIT $limit:
     SqliteError: Hrana: `stream error: `Error { message: "Arguments do not match SQL parameters: value for parameter $limit not found", code: "ARGS_INVALID" }``
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.run (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:268:13)
      at Context.<anonymous> (libsql-test-args.js:75:37)

  12) Params test
       Asynchronous test
         Named
           .all(): SELECT * FROM plep LIMIT $limit:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $limit not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.all (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:321:13)
      at Context.<anonymous> (libsql-test-args.js:80:37)

  13) Params test
       Asynchronous test
         Named
           .get(): SELECT * FROM plep WHERE quantity = $q:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $q not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.get (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:281:13)
      at Context.<anonymous> (libsql-test-args.js:70:37)

  14) Params test
       Asynchronous test
         Named
           .run(): SELECT * FROM plep WHERE quantity = $q:
     SqliteError: Hrana: `stream error: `Error { message: "Arguments do not match SQL parameters: value for parameter $q not found", code: "ARGS_INVALID" }``
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.run (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:268:13)
      at Context.<anonymous> (libsql-test-args.js:75:37)

  15) Params test
       Asynchronous test
         Named
           .all(): SELECT * FROM plep WHERE quantity = $q:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $q not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.all (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:321:13)
      at Context.<anonymous> (libsql-test-args.js:80:37)

  16) Params test
       Asynchronous test
         Named
           .get(): SELECT * FROM plep WHERE quantity = $quantity:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $quantity not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.get (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:281:13)
      at Context.<anonymous> (libsql-test-args.js:70:37)

  17) Params test
       Asynchronous test
         Named
           .run(): SELECT * FROM plep WHERE quantity = $quantity:
     SqliteError: Hrana: `stream error: `Error { message: "Arguments do not match SQL parameters: value for parameter $quantity not found", code: "ARGS_INVALID" }``
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.run (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:268:13)
      at Context.<anonymous> (libsql-test-args.js:75:37)

  18) Params test
       Asynchronous test
         Named
           .all(): SELECT * FROM plep WHERE quantity = $quantity:
     SqliteError: Hrana: `cursor error: `error at step 0: (error code: ARGS_INVALID) `Arguments do not match SQL parameters: value for parameter $quantity not found```
      at convertError (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:21:18)
      at Statement.all (/Users/jocolina/Weez/em/node_modules/libsql/compat.js:321:13)
      at Context.<anonymous> (libsql-test-args.js:80:37)


(Also interesting to note that the error for .all and .get is a cursor error but run is a stream error)

jsmrcaga avatar Aug 31 '25 16:08 jsmrcaga