@gjsify/sqlite 0.52.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{OutOfRangeError as e}from"./errors.js";function convertValue(t,n){if(t==null)return null;if(typeof t==`number`){if(Number.isInteger(t)&&!Number.isSafeInteger(t)){if(!n)throw new e(`Value is too large to be represented as a JavaScript number: ${t}`);return BigInt(t)}return n&&Number.isInteger(t)?BigInt(t):t}if(typeof t==`bigint`){if(!n){if(t>BigInt(2**53-1)||t<BigInt(-(2**53-1)))throw new e(`Value is too large to be represented as a JavaScript number: ${t}`);return Number(t)}return t}if(typeof t==`string`||t instanceof Uint8Array)return t;let r=t;return typeof r.toArray==`function`?new Uint8Array(r.toArray()):t}function readRow(e,t,n){let r=e.get_n_columns();if(n.returnArrays){let i=[];for(let a=0;a<r;a++){let r=e.get_value_at(a,t);i.push(convertValue(r,n.readBigInts))}return i}let i=Object.create(null);for(let a=0;a<r;a++){let r=e.get_column_name(a);i[r]=convertValue(e.get_value_at(a,t),n.readBigInts)}return i}function readAllRows(e,t){let n=e.get_n_rows(),r=[];for(let i=0;i<n;i++){let n=readRow(e,i,t);n!==void 0&&r.push(n)}return r}function readFirstRow(e,t){if(e.get_n_rows()!==0)return readRow(e,0,t)}export{readAllRows,readFirstRow,readRow};
1
+ import"./_virtual/_rolldown/runtime.js";import{OutOfRangeError as e}from"./errors.js";const t=BigInt(2**53-1),n=/^[+-]?\d+$/;function convertIntegerText(r,i){if(n.test(r)){let n=BigInt(r);if(i)return n;if(n>t||n<-t)throw new e(`Value is too large to be represented as a JavaScript number: ${n}`);return Number(n)}let a=Number(r);return r.trim()!==``&&Number.isFinite(a)?a:r}function convertValue(t,n,r=!1){if(t==null)return null;if(r&&typeof t==`string`)return convertIntegerText(t,n);if(typeof t==`number`){if(Number.isInteger(t)&&!Number.isSafeInteger(t)){if(!n)throw new e(`Value is too large to be represented as a JavaScript number: ${t}`);return BigInt(t)}return n&&Number.isInteger(t)?BigInt(t):t}if(typeof t==`bigint`){if(!n){if(t>BigInt(2**53-1)||t<BigInt(-(2**53-1)))throw new e(`Value is too large to be represented as a JavaScript number: ${t}`);return Number(t)}return t}if(typeof t==`string`||t instanceof Uint8Array)return t;let i=t;return typeof i.toArray==`function`?new Uint8Array(i.toArray()):t}function readRow(e,t,n){let r=e.get_n_columns();if(n.returnArrays){let i=[];for(let a=0;a<r;a++){let r=e.get_value_at(a,t);i.push(convertValue(r,n.readBigInts,n.textColumns?.[a]))}return i}let i=Object.create(null);for(let a=0;a<r;a++){let r=e.get_column_name(a);i[r]=convertValue(e.get_value_at(a,t),n.readBigInts,n.textColumns?.[a])}return i}function readAllRows(e,t){let n=e.get_n_rows(),r=[];for(let i=0;i<n;i++){let n=readRow(e,i,t);n!==void 0&&r.push(n)}return r}function readFirstRow(e,t){if(e.get_n_rows()!==0)return readRow(e,0,t)}export{readAllRows,readFirstRow,readRow};
@@ -1,2 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{ConstructCallRequiredError as e,InvalidArgTypeError as t,InvalidStateError as n,InvalidUrlSchemeError as r,SqliteError as i,isNodeSqliteError as a,sqliteErrorMessage as o}from"./errors.js";import{convertParameterSyntax as s}from"./parameter-syntax.js";import{parseSql as c}from"./parse-sql.js";import{StatementSync as l}from"./statement-sync.js";import u from"@girs/gda-6.0";import{lastPathSeparatorIndex as d}from"@gjsify/utils/core";const f=Symbol.for(`sqlite-type`);function parsePath(e){if(typeof e==`string`){if(e.includes(`\0`))throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`);return e}if(e instanceof URL){if(e.protocol!==`file:`)throw new r;let n=e.pathname;if(n.includes(`\0`))throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`);return n}if(e instanceof Uint8Array){for(let n=0;n<e.length;n++)if(e[n]===0)throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`);return new TextDecoder().decode(e)}throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`)}function validateOptions(e){if(e===void 0)return{};if(typeof e!=`object`||!e)throw new t(`The "options" argument must be an object.`);let n=e,r={};if(n.open!==void 0){if(typeof n.open!=`boolean`)throw new t(`The "options.open" argument must be a boolean.`);r.open=n.open}if(n.readOnly!==void 0){if(typeof n.readOnly!=`boolean`)throw new t(`The "options.readOnly" argument must be a boolean.`);r.readOnly=n.readOnly}if(n.timeout!==void 0){if(typeof n.timeout!=`number`||!Number.isInteger(n.timeout))throw new t(`The "options.timeout" argument must be an integer.`);r.timeout=n.timeout}if(n.enableForeignKeyConstraints!==void 0){if(typeof n.enableForeignKeyConstraints!=`boolean`)throw new t(`The "options.enableForeignKeyConstraints" argument must be a boolean.`);r.enableForeignKeyConstraints=n.enableForeignKeyConstraints}if(n.enableDoubleQuotedStringLiterals!==void 0){if(typeof n.enableDoubleQuotedStringLiterals!=`boolean`)throw new t(`The "options.enableDoubleQuotedStringLiterals" argument must be a boolean.`);r.enableDoubleQuotedStringLiterals=n.enableDoubleQuotedStringLiterals}if(n.readBigInts!==void 0){if(typeof n.readBigInts!=`boolean`)throw new t(`The "options.readBigInts" argument must be a boolean.`);r.readBigInts=n.readBigInts}if(n.returnArrays!==void 0){if(typeof n.returnArrays!=`boolean`)throw new t(`The "options.returnArrays" argument must be a boolean.`);r.returnArrays=n.returnArrays}if(n.allowBareNamedParameters!==void 0){if(typeof n.allowBareNamedParameters!=`boolean`)throw new t(`The "options.allowBareNamedParameters" argument must be a boolean.`);r.allowBareNamedParameters=n.allowBareNamedParameters}if(n.allowUnknownNamedParameters!==void 0){if(typeof n.allowUnknownNamedParameters!=`boolean`)throw new t(`The "options.allowUnknownNamedParameters" argument must be a boolean.`);r.allowUnknownNamedParameters=n.allowUnknownNamedParameters}if(n.defensive!==void 0){if(typeof n.defensive!=`boolean`)throw new t(`The "options.defensive" argument must be a boolean.`);r.defensive=n.defensive}if(n.allowExtension!==void 0){if(typeof n.allowExtension!=`boolean`)throw new t(`The "options.allowExtension" argument must be a boolean.`);r.allowExtension=n.allowExtension}return r}var DatabaseSync=class{#e=null;#t;#n;#r;#i=!1;constructor(t,n){if(!new.target)throw new e(`DatabaseSync`);this.#t=parsePath(t),this.#n=validateOptions(n),this.#r=this.#t===`:memory:`,this.#n.open!==!1&&this.open()}get[f](){return`node:sqlite`}get isOpen(){return this.#e!==null&&this.#e.is_opened()}get isTransaction(){return this.#a(),this.#i}open(){if(this.isOpen)throw new n(`database is already open`);try{if(this.#r)this.#e=u.Connection.new_from_string(`SQLite`,`DB_DIR=;DB_NAME=:memory:`,null,u.ConnectionOptions.NONE);else{let e=d(this.#t),t=e>=0?this.#t.substring(0,e):`.`,n=e>=0?this.#t.substring(e+1):this.#t,r=`DB_DIR=${t};DB_NAME=${n.endsWith(`.db`)?n.slice(0,-3):n}`,i=this.#n.readOnly?u.ConnectionOptions.READ_ONLY:u.ConnectionOptions.NONE;this.#e=u.Connection.new_from_string(`SQLite`,r,null,i)}this.#e.open()}catch(e){throw this.#e=null,new i(o(e))}this.#s()}close(){if(!this.isOpen)throw new n(`database is not open`);this.#e.close(),this.#e=null,this.#i=!1}sqlExec(e){if(this.#a(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);try{let t=this.#l(e);for(let e of t){let[t]=this.#o(e);this.#c(t)}}catch(e){throw a(e)?e:new i(o(e))}this.#u(e)}prepare(e,n){if(this.#a(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);let[r,c]=s(e);try{this.#o(r)}catch(e){throw a(e)?e:new i(o(e))}let u={readBigInts:this.#n.readBigInts??!1,returnArrays:this.#n.returnArrays??!1,allowBareNamedParameters:this.#n.allowBareNamedParameters??!0,allowUnknownNamedParameters:this.#n.allowUnknownNamedParameters??!1};return l._create(this.#e,e,u,c)}location(e){if(this.#a(),e!==void 0&&typeof e!=`string`)throw new t(`The "dbName" argument must be a string.`);return this.#r?null:this.#t}[Symbol.dispose](){this.isOpen&&this.close()}#a(){if(!this.isOpen)throw new n(`database is not open`)}#o(e){return c(this.#e,e)}#s(){let e=this.#e,runPragma=t=>{let[n]=this.#o(t);e.statement_execute_select(n,null)};this.#n.enableForeignKeyConstraints===!1?runPragma(`PRAGMA foreign_keys = OFF`):runPragma(`PRAGMA foreign_keys = ON`),this.#n.timeout!==void 0&&this.#n.timeout>0&&runPragma(`PRAGMA busy_timeout = ${this.#n.timeout}`)}#c(e){if(e.get_statement_type()===u.SqlStatementType.SELECT)this.#e.statement_execute_select(e,null);else try{this.#e.statement_execute_non_select(e,null)}catch{this.#e.statement_execute_select(e,null)}}#l(e){let t=[],n=``,r=e.length,i=0,flush=()=>{let e=n.trim();e.length>0&&t.push(e),n=``};for(;i<r;){let t=e[i],a=e[i+1];if(t===`-`&&a===`-`){let t=i+2;for(;t<r&&e[t]!==`
2
- `;)t++;i=t;continue}if(t===`/`&&a===`*`){let t=i+2;for(;t<r&&!(e[t]===`*`&&e[t+1]===`/`);)t++;i=t<r?t+2:r,n+=` `;continue}if(t===`'`||t===`"`||t==="`"||t===`[`){let a=t===`[`?`]`:t,o=t!==`[`,s=i+1;for(n+=t;s<r;){if(e[s]===a){if(o&&e[s+1]===a){n+=a+a,s+=2;continue}n+=a,s++;break}n+=e[s],s++}i=s;continue}if(t===`;`){flush(),i++;continue}n+=t,i++}return flush(),t}#u(e){let t=e.trim().toUpperCase();/\bBEGIN\b/.test(t)&&(this.#i=!0),(/\bCOMMIT\b/.test(t)||/\bROLLBACK\b/.test(t))&&(this.#i=!1)}};DatabaseSync.prototype.exec=DatabaseSync.prototype.sqlExec;export{DatabaseSync};
1
+ import"./_virtual/_rolldown/runtime.js";import{ConstructCallRequiredError as e,InvalidArgTypeError as t,InvalidStateError as n,InvalidUrlSchemeError as r,SqliteError as i,isNodeSqliteError as a,sqliteErrorMessage as o}from"./errors.js";import{executeStatement as s}from"./execution.js";import{convertParameterSyntax as c}from"./parameter-syntax.js";import{parseSql as l}from"./parse-sql.js";import{sqlRegions as u}from"./sql-regions.js";import{rewriteExistsSubqueries as d}from"./exists-subquery.js";import{StatementSync as f}from"./statement-sync.js";import p from"@girs/gda-6.0";import{lastPathSeparatorIndex as m}from"@gjsify/utils/core";const h=Symbol.for(`sqlite-type`);function parsePath(e){if(typeof e==`string`){if(e.includes(`\0`))throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`);return e}if(e instanceof URL){if(e.protocol!==`file:`)throw new r;let n=e.pathname;if(n.includes(`\0`))throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`);return n}if(e instanceof Uint8Array){for(let n=0;n<e.length;n++)if(e[n]===0)throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`);return new TextDecoder().decode(e)}throw new t(`The "path" argument must be a string, Uint8Array, or URL without null bytes.`)}function validateOptions(e){if(e===void 0)return{};if(typeof e!=`object`||!e)throw new t(`The "options" argument must be an object.`);let n=e,r={};if(n.open!==void 0){if(typeof n.open!=`boolean`)throw new t(`The "options.open" argument must be a boolean.`);r.open=n.open}if(n.readOnly!==void 0){if(typeof n.readOnly!=`boolean`)throw new t(`The "options.readOnly" argument must be a boolean.`);r.readOnly=n.readOnly}if(n.timeout!==void 0){if(typeof n.timeout!=`number`||!Number.isInteger(n.timeout))throw new t(`The "options.timeout" argument must be an integer.`);r.timeout=n.timeout}if(n.enableForeignKeyConstraints!==void 0){if(typeof n.enableForeignKeyConstraints!=`boolean`)throw new t(`The "options.enableForeignKeyConstraints" argument must be a boolean.`);r.enableForeignKeyConstraints=n.enableForeignKeyConstraints}if(n.enableDoubleQuotedStringLiterals!==void 0){if(typeof n.enableDoubleQuotedStringLiterals!=`boolean`)throw new t(`The "options.enableDoubleQuotedStringLiterals" argument must be a boolean.`);r.enableDoubleQuotedStringLiterals=n.enableDoubleQuotedStringLiterals}if(n.readBigInts!==void 0){if(typeof n.readBigInts!=`boolean`)throw new t(`The "options.readBigInts" argument must be a boolean.`);r.readBigInts=n.readBigInts}if(n.returnArrays!==void 0){if(typeof n.returnArrays!=`boolean`)throw new t(`The "options.returnArrays" argument must be a boolean.`);r.returnArrays=n.returnArrays}if(n.allowBareNamedParameters!==void 0){if(typeof n.allowBareNamedParameters!=`boolean`)throw new t(`The "options.allowBareNamedParameters" argument must be a boolean.`);r.allowBareNamedParameters=n.allowBareNamedParameters}if(n.allowUnknownNamedParameters!==void 0){if(typeof n.allowUnknownNamedParameters!=`boolean`)throw new t(`The "options.allowUnknownNamedParameters" argument must be a boolean.`);r.allowUnknownNamedParameters=n.allowUnknownNamedParameters}if(n.defensive!==void 0){if(typeof n.defensive!=`boolean`)throw new t(`The "options.defensive" argument must be a boolean.`);r.defensive=n.defensive}if(n.allowExtension!==void 0){if(typeof n.allowExtension!=`boolean`)throw new t(`The "options.allowExtension" argument must be a boolean.`);r.allowExtension=n.allowExtension}return r}var DatabaseSync=class{#e=null;#t;#n;#r;#i=!1;constructor(t,n){if(!new.target)throw new e(`DatabaseSync`);this.#t=parsePath(t),this.#n=validateOptions(n),this.#r=this.#t===`:memory:`,this.#n.open!==!1&&this.open()}get[h](){return`node:sqlite`}get isOpen(){return this.#e!==null&&this.#e.is_opened()}get isTransaction(){return this.#a(),this.#i}open(){if(this.isOpen)throw new n(`database is already open`);try{if(this.#r)this.#e=p.Connection.new_from_string(`SQLite`,`DB_DIR=;DB_NAME=:memory:`,null,p.ConnectionOptions.NONE);else{let e=m(this.#t),t=e>=0?this.#t.substring(0,e):`.`,n=e>=0?this.#t.substring(e+1):this.#t,r=`DB_DIR=${t};DB_NAME=${n.endsWith(`.db`)?n.slice(0,-3):n}`,i=this.#n.readOnly?p.ConnectionOptions.READ_ONLY:p.ConnectionOptions.NONE;this.#e=p.Connection.new_from_string(`SQLite`,r,null,i)}this.#e.open()}catch(e){throw this.#e=null,new i(o(e))}this.#s()}close(){if(!this.isOpen)throw new n(`database is not open`);this.#e.close(),this.#e=null,this.#i=!1}sqlExec(e){if(this.#a(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);try{let t=this.#c(e);for(let e of t){let[t]=this.#o(d(e));s(this.#e,t,null,()=>void 0)}}catch(e){throw a(e)?e:new i(o(e))}this.#l(e)}prepare(e,n){if(this.#a(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);let[r,s]=c(e);try{this.#o(d(r))}catch(e){throw a(e)?e:new i(o(e))}let l={readBigInts:this.#n.readBigInts??!1,returnArrays:this.#n.returnArrays??!1,allowBareNamedParameters:this.#n.allowBareNamedParameters??!0,allowUnknownNamedParameters:this.#n.allowUnknownNamedParameters??!1};return f._create(this.#e,e,l,s)}location(e){if(this.#a(),e!==void 0&&typeof e!=`string`)throw new t(`The "dbName" argument must be a string.`);return this.#r?null:this.#t}[Symbol.dispose](){this.isOpen&&this.close()}#a(){if(!this.isOpen)throw new n(`database is not open`)}#o(e){return l(this.#e,e)}#s(){let runPragma=e=>{let[t]=this.#o(e);s(this.#e,t,null,()=>void 0)};this.#n.enableForeignKeyConstraints===!1?runPragma(`PRAGMA foreign_keys = OFF`):runPragma(`PRAGMA foreign_keys = ON`),this.#n.timeout!==void 0&&this.#n.timeout>0&&runPragma(`PRAGMA busy_timeout = ${this.#n.timeout}`)}#c(e){let t=[],n=``,flush=()=>{let e=n.trim();e.length>0&&t.push(e),n=``};for(let t of u(e))if(t.kind===`code`){let r=e.slice(t.start,t.end).split(`;`);n+=r[0];for(let e of r.slice(1))flush(),n+=e}else t.kind===`block-comment`?n+=` `:n+=e.slice(t.start,t.end);return flush(),t}#l(e){let t=e.trim().toUpperCase();/\bBEGIN\b/.test(t)&&(this.#i=!0),(/\bCOMMIT\b/.test(t)||/\bROLLBACK\b/.test(t))&&(this.#i=!1)}};DatabaseSync.prototype.exec=DatabaseSync.prototype.sqlExec;export{DatabaseSync};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{SqliteError as e}from"./errors.js";import t from"@girs/gda-6.0";import n from"@girs/gobject-2.0";let r=null;function typeNull(){if(r===null&&(t.value_new_null(),r=n.type_from_name(`GdaNull`),!r))throw new e(`libgda did not register GdaNull`);return r}const i=new Set([`gint`,`guint`,`gint64`,`guint64`,`gboolean`,`GDate`,`GdaTime`,`GDateTime`]);var ColumnTypes=class{types;constructor(e=null){this.types=e}get textColumns(){return(this.types??[]).map(e=>e===n.TYPE_STRING)}};function integerColumns(e){return new ColumnTypes(Array.from({length:e},()=>n.TYPE_STRING))}function executeStatement(e,t,n,r,i){let a=null;try{return a=execute(e,t,n,i),a&&assertTyped(a),r(a,i?.textColumns??[])}finally{a&&releasePreparedStatement(a),e.del_prepared_statement(t)}}function execute(e,n,r,i){if(n.get_statement_type()===t.SqlStatementType.SELECT)return i?executeTyped(e,n,r,i):e.statement_execute_select_full(n,r,t.StatementModelUsage.CURSOR_FORWARD,null);let a=t.Batch.new();a.add_statement(n);let[o]=e.batch_execute(a,r,t.StatementModelUsage.RANDOM_ACCESS);return!o||o instanceof t.Set?null:o}function executeTyped(t,n,r,i){let a=i.types===null;a&&(i.types=probeColumns(t,n,r));let o=selectWith(t,n,r,i.types);if(matches(o,i.types))return o;if(releasePreparedStatement(o),t.del_prepared_statement(n),a)throw new e(`the result columns changed between two executions`);i.types=probeColumns(t,n,r);let s=selectWith(t,n,r,i.types);if(matches(s,i.types))return s;throw releasePreparedStatement(s),new e(`the result columns changed between two executions`)}function matches(e,t){if(e.get_n_columns()!==t.length)return!1;for(let r=0;r<t.length;r++){if(t[r]===n.TYPE_STRING)continue;let a=n.type_name(e.describe_column(r).get_g_type());if(a!==null&&i.has(a))return!1}return!0}function selectWith(e,r,i,a){return e.statement_execute_select_full(r,i,t.StatementModelUsage.RANDOM_ACCESS,[...a,n.TYPE_NONE])}function probeColumns(e,r,a){let o=e.statement_execute_select_full(r,a,t.StatementModelUsage.CURSOR_FORWARD,null);try{assertTyped(o);let e=[];for(let t=0;t<o.get_n_columns();t++){let r=n.type_name(o.describe_column(t).get_g_type());e.push(r!==null&&i.has(r)?n.TYPE_STRING:typeNull())}return e}finally{releasePreparedStatement(o),e.del_prepared_statement(r)}}function assertTyped(t){let n=t.get_n_columns();for(let r=0;r<n;r++){let n=t.describe_column(r);if(n&&!n.get_g_type())throw new e(`libgda could not type a result column; the connection has lost its SQLite provider`)}}function releasePreparedStatement(e){e.prepared_stmt=null}export{ColumnTypes,executeStatement,integerColumns};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{sqlRegions as e}from"./sql-regions.js";const t=/exists/i;function rewriteExistsSubqueries(n){if(!t.test(n))return n;let r=e(n),i=[],a=0,o={at:0,region:0};for(;o.at<n.length&&(seekToCode(n,r,o),!(o.at>=n.length));){let e=o.at;if(isExistsAt(n,r,o)){let t=openParenAfter(n,r,o),s=t<0?-1:matchingParen(n,r,t);if(s>=0){i.push(n.slice(a,e),`(1 IN (SELECT 1 FROM (`),i.push(rewriteExistsSubqueries(n.slice(t+1,s))),i.push(`)))`),a=s+1,o.at=s+1;continue}}o.at=e+1}return a===0?n:(i.push(n.slice(a)),i.join(``))}function seekToCode(e,t,n){for(;n.at<e.length;){for(;n.region<t.length-1&&t[n.region].end<=n.at;)n.region++;if(t[n.region].kind===`code`)return;n.at=t[n.region].end}}function isExistsAt(e,t,n){let r=n.at;return e.slice(r,r+6).toUpperCase()!==`EXISTS`||r>0&&/[A-Za-z0-9_$]/.test(e[r-1])?!1:openParenAfter(e,t,n)>=0}function openParenAfter(e,t,n){let r=n.at+6,i=n.region;for(;r<e.length;){for(;i<t.length-1&&t[i].end<=r;)i++;let n=t[i];if(n.kind===`code`){if(e[r]===`(`)return r;if(!/\s/.test(e[r]))return-1;r++}else r=n.end}return-1}function matchingParen(e,t,n){let r=0,i={at:n,region:0};for(;i.at<e.length&&(seekToCode(e,t,i),!(i.at>=e.length));){let t=e[i.at];if(t===`(`)r++;else if(t===`)`&&--r===0)return i.at;i.at++}return-1}export{rewriteExistsSubqueries};
@@ -0,0 +1,2 @@
1
+ import"./_virtual/_rolldown/runtime.js";function sqlRegions(e){let t=[],n=0,r=0;for(;r<e.length;){let i=r,a=e[r],o=`quoted`;if(a===`'`||a===`"`||a==="`"||a===`[`){let t=a===`[`?`]`:a,n=a!==`[`;for(r++;r<e.length;){if(e[r]===t){if(n&&e[r+1]===t){r+=2;continue}r++;break}r++}}else if(a===`-`&&e[r+1]===`-`)for(o=`line-comment`,r+=2;r<e.length&&e[r]!==`
2
+ `;)r++;else if(a===`/`&&e[r+1]===`*`){for(o=`block-comment`,r+=2;r<e.length&&!(e[r]===`*`&&e[r+1]===`/`);)r++;r=r<e.length?r+2:e.length}else{r++;continue}i>n&&t.push({kind:`code`,start:n,end:i}),t.push({kind:o,start:i,end:r}),n=r}return n<e.length&&t.push({kind:`code`,start:n,end:e.length}),t}export{sqlRegions};
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{IllegalConstructorError as e,InvalidArgTypeError as t,InvalidArgValueError as n,SqliteError as r,isNodeSqliteError as i,sqliteErrorMessage as a}from"./errors.js";import{readAllRows as o,readFirstRow as s}from"./data-model-reader.js";import{convertParameterSyntax as c}from"./parameter-syntax.js";import{parseSql as l}from"./parse-sql.js";import{bindStringHolders as u}from"./param-binding.js";import d from"@girs/gda-6.0";const f=Symbol(`StatementSync.internal`);function isNamedArgObject(e){return typeof e==`object`&&!!e&&!(e instanceof Uint8Array)&&!ArrayBuffer.isView(e)}function validateBindValue(e,n){if(e==null)return;let r=typeof e;if(!(r===`number`||r===`bigint`||r===`string`||r===`boolean`)&&!(e instanceof Uint8Array||e instanceof ArrayBuffer)&&!ArrayBuffer.isView(e))throw new t(`Provided value cannot be bound to SQLite parameter ${n}.`)}function sqlLiteral(e){if(e==null)return`NULL`;if(typeof e==`number`){if(Number.isNaN(e))return`NULL`;if(e===1/0)return`9e999`;if(e===-1/0)return`-9e999`;let t=String(e);return Number.isInteger(e)&&!t.includes(`e`)&&!t.includes(`E`)?`${t}.0`:t}if(typeof e==`boolean`)return e?`1`:`0`;if(typeof e==`bigint`){if(e>9223372036854775807n||e<-9223372036854775808n)throw new n(`BigInt value is too large to bind.`);return String(e)}if(e instanceof Uint8Array){let t=``;for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,`0`);return`X'`+t+`'`}return ArrayBuffer.isView(e)?sqlLiteral(new Uint8Array(e.buffer)):`NULL`}var p=class StatementSync{#e;#t;#n;#r;#i;#a;#o;constructor(t,n,r,i,a){if(t!==f)throw new e;this.#e=n,this.#t=r,this.#n=a,this.#r=i.readBigInts??!1,this.#i=i.returnArrays??!1,this.#a=i.allowBareNamedParameters??!0,this.#o=i.allowUnknownNamedParameters??!1}static _create(e,t,n,r){return new StatementSync(f,e,t,n,r)}get sourceSQL(){return this.#t}get expandedSQL(){return this.#t}#s(){return{readBigInts:this.#r,returnArrays:this.#i}}#c(){let e=-1;for(let t of this.#n)t.position>e&&(e=t.position);return e}#l(e){let t=new Map;if(this.#n.length===0){if(e.length>0&&!isNamedArgObject(e[0]))throw new r(`column index out of range`,25,`column index out of range`);return{sql:this.#t,strings:t}}let n=null,i=e;e.length>0&&isNamedArgObject(e[0])&&(n=e[0],i=e.slice(1));let a=new Map;if(n){for(let e of this.#n){if(e.position>=0)continue;let t=e.originalName,i,o=!1;if(t in n&&(i=n[t],o=!0),!o&&this.#a){let e=t.replace(/^[$:@]/,``);e in n&&(i=n[e],o=!0)}if(!o&&!this.#a){let e=t.replace(/^[$:@]/,``);if(e in n)throw new r(`Unknown named parameter '${e}'`,0,`Unknown named parameter '${e}'`)}o&&(validateBindValue(i,this.#n.indexOf(e)+1),a.set(e.gdaId,i))}if(!this.#o){let e=new Set;for(let t of this.#n)t.position>=0||(e.add(t.originalName),e.add(t.originalName.replace(/^[$:@]/,``)));for(let t of Object.keys(n))if(!e.has(t)&&!e.has(t.replace(/^[$:@]/,``)))throw new r(`Unknown named parameter '${t}'`,0,`Unknown named parameter '${t}'`)}for(let e=0;e<i.length;e++){if(e>this.#c())throw new r(`column index out of range`,25,`column index out of range`);validateBindValue(i[e],e+1),a.set(`p${e}`,i[e])}}else{let e=this.#c()+1;if(i.length>e&&e>0)throw new r(`column index out of range`,25,`column index out of range`);for(let t=0;t<Math.min(i.length,e);t++)validateBindValue(i[t],t+1),a.set(`p${t}`,i[t])}let[o]=c(this.#t,e=>{let n=a.get(e.gdaId);return typeof n==`string`?(t.set(e.gdaId,n),`##${e.gdaId}::string`):sqlLiteral(n)});return{sql:o,strings:t}}#u(e){let{sql:t,strings:n}=this.#l(e);try{let[e,r]=l(this.#e,t);if(u(r,n),e.get_statement_type()===d.SqlStatementType.SELECT)return{model:this.#e.statement_execute_select(e,r),isSelect:!0};try{return this.#e.statement_execute_non_select(e,r),{model:null,isSelect:!1}}catch{return{model:this.#e.statement_execute_select(e,r),isSelect:!0}}}catch(e){throw i(e)?e:new r(a(e))}}run(...e){this.#u(e);let t=0,n=0,r=this.#e.execute_select_command(`SELECT changes()`);r&&r.get_n_rows()>0&&(t=r.get_value_at(0,0));let i=this.#e.execute_select_command(`SELECT last_insert_rowid()`);return i&&i.get_n_rows()>0&&(n=i.get_value_at(0,0)),this.#r&&(t=BigInt(t),n=BigInt(n)),{changes:t,lastInsertRowid:n}}get(...e){let{model:t}=this.#u(e);if(!(!t||t.get_n_rows()===0))return s(t,this.#s())}all(...e){let{model:t}=this.#u(e);return t?o(t,this.#s()):[]}setReadBigInts(e){if(typeof e!=`boolean`)throw new t(`The "readBigInts" argument must be a boolean.`);this.#r=e}setReturnArrays(e){if(typeof e!=`boolean`)throw new t(`The "returnArrays" argument must be a boolean.`);this.#i=e}setAllowBareNamedParameters(e){if(typeof e!=`boolean`)throw new t(`The "allowBareNamedParameters" argument must be a boolean.`);this.#a=e}setAllowUnknownNamedParameters(e){if(typeof e!=`boolean`)throw new t(`The "allowUnknownNamedParameters" argument must be a boolean.`);this.#o=e}};export{p as StatementSync};
1
+ import"./_virtual/_rolldown/runtime.js";import{IllegalConstructorError as e,InvalidArgTypeError as t,InvalidArgValueError as n,SqliteError as r,isNodeSqliteError as i,sqliteErrorMessage as a}from"./errors.js";import{readAllRows as o,readFirstRow as s}from"./data-model-reader.js";import{ColumnTypes as c,executeStatement as l,integerColumns as u}from"./execution.js";import{convertParameterSyntax as d}from"./parameter-syntax.js";import{parseSql as f}from"./parse-sql.js";import{rewriteExistsSubqueries as p}from"./exists-subquery.js";import{bindStringHolders as m}from"./param-binding.js";const h=Symbol(`StatementSync.internal`);function isNamedArgObject(e){return typeof e==`object`&&!!e&&!(e instanceof Uint8Array)&&!ArrayBuffer.isView(e)}function validateBindValue(e,n){if(e==null)return;let r=typeof e;if(!(r===`number`||r===`bigint`||r===`string`||r===`boolean`)&&!(e instanceof Uint8Array||e instanceof ArrayBuffer)&&!ArrayBuffer.isView(e))throw new t(`Provided value cannot be bound to SQLite parameter ${n}.`)}function sqlLiteral(e){if(e==null)return`NULL`;if(typeof e==`number`){if(Number.isNaN(e))return`NULL`;if(e===1/0)return`9e999`;if(e===-1/0)return`-9e999`;let t=String(e);return Number.isInteger(e)&&!t.includes(`e`)&&!t.includes(`E`)?`${t}.0`:t}if(typeof e==`boolean`)return e?`1`:`0`;if(typeof e==`bigint`){if(e>9223372036854775807n||e<-9223372036854775808n)throw new n(`BigInt value is too large to bind.`);return String(e)}if(e instanceof Uint8Array){let t=``;for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,`0`);return`X'`+t+`'`}return ArrayBuffer.isView(e)?sqlLiteral(new Uint8Array(e.buffer)):`NULL`}var g=class StatementSync{#e;#t;#n;#r;#i;#a;#o;#s=new c;constructor(t,n,r,i,a){if(t!==h)throw new e;this.#e=n,this.#t=r,this.#n=a,this.#r=i.readBigInts??!1,this.#i=i.returnArrays??!1,this.#a=i.allowBareNamedParameters??!0,this.#o=i.allowUnknownNamedParameters??!1}static _create(e,t,n,r){return new StatementSync(h,e,t,n,r)}get sourceSQL(){return this.#t}get expandedSQL(){return this.#t}#c(e){return{readBigInts:this.#r,returnArrays:this.#i,textColumns:e}}#l(){let e=-1;for(let t of this.#n)t.position>e&&(e=t.position);return e}#u(e){let t=new Map;if(this.#n.length===0){if(e.length>0&&!isNamedArgObject(e[0]))throw new r(`column index out of range`,25,`column index out of range`);return{sql:this.#t,strings:t}}let n=null,i=e;e.length>0&&isNamedArgObject(e[0])&&(n=e[0],i=e.slice(1));let a=new Map;if(n){for(let e of this.#n){if(e.position>=0)continue;let t=e.originalName,i,o=!1;if(t in n&&(i=n[t],o=!0),!o&&this.#a){let e=t.replace(/^[$:@]/,``);e in n&&(i=n[e],o=!0)}if(!o&&!this.#a){let e=t.replace(/^[$:@]/,``);if(e in n)throw new r(`Unknown named parameter '${e}'`,0,`Unknown named parameter '${e}'`)}o&&(validateBindValue(i,this.#n.indexOf(e)+1),a.set(e.gdaId,i))}if(!this.#o){let e=new Set;for(let t of this.#n)t.position>=0||(e.add(t.originalName),e.add(t.originalName.replace(/^[$:@]/,``)));for(let t of Object.keys(n))if(!e.has(t)&&!e.has(t.replace(/^[$:@]/,``)))throw new r(`Unknown named parameter '${t}'`,0,`Unknown named parameter '${t}'`)}for(let e=0;e<i.length;e++){if(e>this.#l())throw new r(`column index out of range`,25,`column index out of range`);validateBindValue(i[e],e+1),a.set(`p${e}`,i[e])}}else{let e=this.#l()+1;if(i.length>e&&e>0)throw new r(`column index out of range`,25,`column index out of range`);for(let t=0;t<Math.min(i.length,e);t++)validateBindValue(i[t],t+1),a.set(`p${t}`,i[t])}let[o]=d(this.#t,e=>{let n=a.get(e.gdaId);return typeof n==`string`?(t.set(e.gdaId,n),`##${e.gdaId}::string`):sqlLiteral(n)});return{sql:o,strings:t}}#d(e,t,n){let{sql:o,strings:s}=this.#u(e);try{let[e,r]=f(this.#e,p(o));return m(r,s),l(this.#e,e,r,t,n)}catch(e){throw i(e)?e:new r(a(e))}}run(...e){this.#d(e,()=>void 0);let[t]=f(this.#e,`SELECT changes(), last_insert_rowid()`),[n,i]=l(this.#e,t,null,e=>{if(!e||e.get_n_rows()===0)throw new r(`SELECT changes(), last_insert_rowid() returned no row`);return[BigInt(e.get_value_at(0,0)),BigInt(e.get_value_at(1,0))]},u(2));return this.#r?{changes:n,lastInsertRowid:i}:{changes:Number(n),lastInsertRowid:Number(i)}}get(...e){return this.#d(e,(e,t)=>{if(!(!e||e.get_n_rows()===0))return s(e,this.#c(t))},this.#s)}all(...e){return this.#d(e,(e,t)=>e?o(e,this.#c(t)):[],this.#s)}setReadBigInts(e){if(typeof e!=`boolean`)throw new t(`The "readBigInts" argument must be a boolean.`);this.#r=e}setReturnArrays(e){if(typeof e!=`boolean`)throw new t(`The "returnArrays" argument must be a boolean.`);this.#i=e}setAllowBareNamedParameters(e){if(typeof e!=`boolean`)throw new t(`The "allowBareNamedParameters" argument must be a boolean.`);this.#a=e}setAllowUnknownNamedParameters(e){if(typeof e!=`boolean`)throw new t(`The "allowUnknownNamedParameters" argument must be a boolean.`);this.#o=e}};export{g as StatementSync};
@@ -2,6 +2,8 @@ import type Gda from '@girs/gda-6.0';
2
2
  export interface ReadOptions {
3
3
  readBigInts: boolean;
4
4
  returnArrays: boolean;
5
+ /** Per column: true where libgda was told to hand the value over as text (execution.ts). */
6
+ textColumns?: boolean[];
5
7
  }
6
8
  export declare function readRow(model: Gda.DataModel, row: number, options: ReadOptions): Record<string, unknown> | unknown[] | undefined;
7
9
  export declare function readAllRows(model: Gda.DataModel, options: ReadOptions): (Record<string, unknown> | unknown[])[];
@@ -0,0 +1,52 @@
1
+ import Gda from '@girs/gda-6.0';
2
+ import GObject from '@girs/gobject-2.0';
3
+ /**
4
+ * How the result columns of one prepared statement are read, remembered between its
5
+ * executions.
6
+ *
7
+ * Learning it costs an extra execution (see `probeColumns`), so a `StatementSync` keeps one
8
+ * of these for its lifetime. A column this has never seen typed (NULL in every probed row)
9
+ * is left to libgda; if a later execution types it integer-like, it is probed again.
10
+ */
11
+ export declare class ColumnTypes {
12
+ /** Per column: TYPE_STRING to read as exact text, GdaNull to let libgda decide. */
13
+ types: GObject.GType[] | null;
14
+ constructor(types?: GObject.GType[] | null);
15
+ /** Which columns hold text that `data-model-reader.ts` must convert back. */
16
+ get textColumns(): boolean[];
17
+ }
18
+ /** Every column read as text — for a query whose columns are all known to be integers. */
19
+ export declare function integerColumns(count: number): ColumnTypes;
20
+ /**
21
+ * Execute `stmt`, hand its result to `read`, and leave NOTHING behind on the connection.
22
+ *
23
+ * libgda keeps state per execution that only the connection's close() or the garbage
24
+ * collector would otherwise release, and on a long-lived connection that state runs out:
25
+ *
26
+ * - The connection caches a prepared statement (`GdaSqlitePStmt`) for every
27
+ * `Gda.Statement` it ever executed, holding a STRONG reference to both, until the
28
+ * statement emits `reset` — which ours never do — or the connection closes. This package
29
+ * renders a fresh statement per execution, so the cache grew by one on every call.
30
+ * - Every `GdaSqlitePStmt` holds a GWeakRef to the SQLite provider, and GLib (≥ 2.84) caps
31
+ * the GWeakRefs on one object at 65535. Past it, `g_weak_ref_set()` refuses with
32
+ * "Too many GWeakRef registered", the next prepared statement has no provider, and
33
+ * libgda answers `fuzzy_get_gtype: assertion 'prov != NULL' failed` — a CRITICAL, not an
34
+ * error. Reads on that connection came back typeless or empty with no exception.
35
+ * - A SELECT's data model (`GdaSqliteRecordset`) holds its prepared statement until the
36
+ * model is finalized, and the model is a GJS wrapper the garbage collector frees
37
+ * whenever it gets round to it. Measured: ~70,000 unread models outlive one GC.
38
+ * - `statement_execute_non_select()` has a `last_insert_row` out-parameter. GJS always
39
+ * passes the pointer, so on every INSERT the SQLite provider built and executed a
40
+ * hidden `SELECT * FROM <table> WHERE rowid = ?` — on a statement of its own that the
41
+ * connection cached as above, where no caller can reach it to release it.
42
+ *
43
+ * So: non-SELECTs go through `batch_execute()`, which passes `last_insert_row` as NULL;
44
+ * the connection's cache entry is deleted after every execution; and the data model lets
45
+ * go of its prepared statement as soon as `read` returns. Every object an execution
46
+ * creates is then released before this function does.
47
+ *
48
+ * Do NOT use `GObject.Object.run_dispose()` on the model instead: `GdaSqliteRecordset`'s
49
+ * dispose clears a GWeakRef without re-initialising it, so the second dispose the
50
+ * finalizer runs dereferences a cleared weak ref and the process dies with SIGSEGV.
51
+ */
52
+ export declare function executeStatement<T>(connection: Gda.Connection, stmt: Gda.Statement, params: Gda.Set | null, read: (model: Gda.DataModel | null, textColumns: boolean[]) => T, columns?: ColumnTypes): T;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `EXISTS (S)` → `(1 IN (SELECT 1 FROM (S)))`, for every `EXISTS (` in `sql`.
3
+ *
4
+ * Equivalent by construction: the derived table `S` yields one row per row of `S` and
5
+ * every one of them holds the constant `1`, so `1 IN (…)` is true exactly when `S` yields
6
+ * a row — which is what `EXISTS (S)` means. The derived table is what makes that
7
+ * independent of what `S` projects; `1 IN (S)` on its own would only agree while `S`
8
+ * already projected the constant 1. The `IN` form is the one construct libgda renders
9
+ * correctly: an operation operand that is a sub-SELECT gets ONE pair of parentheses,
10
+ * from `default_render_operation()`, which marks the operand composed rather than
11
+ * parenthesising it a second time.
12
+ *
13
+ * The outer parentheses keep `NOT` and `AND`/`OR` bound to the predicate the caller
14
+ * wrote: without them `NOT EXISTS (S)` would become `NOT 1 IN (…)`, which SQL reads the
15
+ * same way but which no longer looks like the subquery the caller passed.
16
+ *
17
+ * `S` is copied byte for byte, so every parameter, literal and identifier inside it keeps
18
+ * its position and its text — which is what keeps the holders this package binds
19
+ * (`Gda.Set`) lined up with the `?` placeholders of the rendered statement.
20
+ *
21
+ * A nested `EXISTS` inside `S` is rewritten too, and only occurrences in CODE are
22
+ * touched: `sqlRegions()` is what keeps the word out of a string literal, a quoted
23
+ * identifier and a comment. A comment BETWEEN the keyword and its parenthesis counts as
24
+ * nothing at all, because SQLite's own tokenizer skips it there — `EXISTS -- c\n(SELECT …)`
25
+ * is ONE statement and has to be rewritten as one. An `EXISTS` not followed by a `(` — a
26
+ * column, a longer identifier ending in it, prose in a comment — is left alone, as is an
27
+ * unterminated `(`, which is a syntax error libgda should report in its own words.
28
+ *
29
+ * The cost of the IN form, recorded so it is not "optimised" away: SQLite materialises `S`
30
+ * into an ephemeral index (a `LIST SUBQUERY` scan with a bloom filter, measured on 100k
31
+ * rows) where `EXISTS` stops at the first row, and `LIMIT 1` on `S` does NOT bring that
32
+ * plan back (measured). The faster scalar restatement, `(SELECT 1 FROM (S) LIMIT 1) = 1`,
33
+ * answers NULL instead of 0 in a projection when `S` is empty (measured) — so the IN form
34
+ * is the one that is correct in every position.
35
+ */
36
+ export declare function rewriteExistsSubqueries(sql: string): string;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * What a stretch of the SQL text is. Only `code` is parsed; the other three are inert
3
+ * bytes that must be copied through untouched.
4
+ */
5
+ export type SqlRegionKind = 'code' | 'quoted' | 'line-comment' | 'block-comment';
6
+ export interface SqlRegion {
7
+ kind: SqlRegionKind;
8
+ /** Index of the first character, and one past the last. */
9
+ start: number;
10
+ end: number;
11
+ }
12
+ /**
13
+ * Split `sql` into alternating code and inert regions, in source order and covering it
14
+ * exactly — a region is never empty, and no two regions touch. Neither end is
15
+ * necessarily `code`: SQL beginning with a comment yields a first region of that kind, and
16
+ * so does SQL ending in one, so a caller that walks the list must not assume either.
17
+ *
18
+ * A line comment ends BEFORE its terminating newline, so the newline is CODE and the next
19
+ * statement is found from it. That is SQLite's own rule, and it is what lets a consumer
20
+ * write `EXISTS -- why\n(SELECT …)` and have the parenthesis still be the sub-SELECT's.
21
+ *
22
+ * An unterminated quoted region or comment runs to the end of the input, which is what
23
+ * SQLite's own tokenizer does with the same input.
24
+ */
25
+ export declare function sqlRegions(sql: string): SqlRegion[];
@@ -1,4 +1,4 @@
1
- import Gda from '@girs/gda-6.0';
1
+ import type Gda from '@girs/gda-6.0';
2
2
  import { type ParamInfo } from './parameter-syntax.ts';
3
3
  import type { RunResult, StatementSyncOptions } from './types.ts';
4
4
  export declare class StatementSync {
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/sqlite",
3
- "version": "0.52.0",
3
+ "version": "0.54.0",
4
4
  "description": "Node.js sqlite module for Gjs using libgda",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -40,9 +40,9 @@
40
40
  "libgda"
41
41
  ],
42
42
  "devDependencies": {
43
- "@gjsify/cli": "^0.52.0",
43
+ "@gjsify/cli": "^0.54.0",
44
44
  "@gjsify/node-gi": "file:../../../packages/node-gi/node-gi",
45
- "@gjsify/unit": "^0.52.0",
45
+ "@gjsify/unit": "^0.54.0",
46
46
  "@types/node": "^25.9.2",
47
47
  "typescript": "^6.0.3"
48
48
  },
@@ -50,7 +50,7 @@
50
50
  "@girs/gda-6.0": "5.4.0",
51
51
  "@girs/glib-2.0": "5.4.0",
52
52
  "@girs/gobject-2.0": "5.4.0",
53
- "@gjsify/utils": "^0.52.0"
53
+ "@gjsify/utils": "^0.54.0"
54
54
  },
55
55
  "gjsify": {
56
56
  "runtimes": {