@gjsify/sqlite 0.64.12-next.280 → 0.64.12

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{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{parseSql as c}from"./parse-sql.js";import{acquire as l,release as u}from"./connection-pool.js";import{convertParameterSyntax as d}from"./parameter-syntax.js";import{sqlRegions as f}from"./sql-regions.js";import{rewriteExistsSubqueries as p}from"./exists-subquery.js";import{providerSql as m,statementKind as h}from"./statement-kind.js";import{StatementSync as g}from"./statement-sync.js";import _ from"@girs/gda-6.0";import{lastPathSeparatorIndex as v}from"@gjsify/utils/core";const y=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[y](){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{this.#e=l(this.#o(),()=>{let e;if(this.#r)e=_.Connection.new_from_string(`SQLite`,`DB_DIR=;DB_NAME=:memory:`,null,_.ConnectionOptions.NONE);else{let t=v(this.#t),n=t>=0?this.#t.substring(0,t):`.`,r=t>=0?this.#t.substring(t+1):this.#t,i=`DB_DIR=${n};DB_NAME=${r.endsWith(`.db`)?r.slice(0,-3):r}`,a=this.#n.readOnly?_.ConnectionOptions.READ_ONLY:_.ConnectionOptions.NONE;e=_.Connection.new_from_string(`SQLite`,i,null,a)}return e.open(),e})}catch(e){throw this.#e=null,new i(o(e))}this.#c()}close(){if(!this.isOpen)throw new n(`database is not open`);u(this.#o(),this.#e),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=h(e),[n]=this.#s(m(p(e),t));s(this.#e,n,null,()=>void 0,{kind:t})}}catch(e){throw a(e)?e:new i(o(e))}this.#u()}prepare(e,n){if(this.#a(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);let[r,s]=d(e),c=h(r);try{this.#s(m(p(r),c))}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 g._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(){return{path:this.#t,isMemory:this.#r,readOnly:this.#n.readOnly??!1}}#s(e){return c(this.#e,e)}#c(){let runPragma=e=>{let[t]=this.#s(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}`)}#l(e){let t=[],n=``,flush=()=>{let e=n.trim();e.length>0&&t.push(e),n=``};for(let t of f(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}#u(){this.#i=this.#e.get_transaction_status()!==null}};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,toSqliteError as i}from"./errors.js";import{nativeSqlite as a}from"./native.js";import{StatementSync as o}from"./statement-sync.js";const s=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;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[s](){return`node:sqlite`}get isOpen(){return this.#e!==null&&this.#e.is_open}get isTransaction(){return this.#i(),this.#e.in_transaction}open(){if(this.isOpen)throw new n(`database is already open`);let{Database:e,OpenMode:t}=a(),r=this.#n.readOnly?t.READONLY:t.READWRITE_CREATE;try{this.#e=e.open(this.#t,r,!1)}catch(e){throw this.#e=null,i(e)}this.#a()}close(){if(!this.isOpen)throw new n(`database is not open`);this.#e.close(),this.#e=null}sqlExec(e){if(this.#i(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);try{this.#e.exec(e)}catch(e){throw i(e)}}prepare(e,n){if(this.#i(),typeof e!=`string`)throw new t(`The "sql" argument must be a string.`);let r={readBigInts:this.#n.readBigInts??!1,returnArrays:this.#n.returnArrays??!1,allowBareNamedParameters:this.#n.allowBareNamedParameters??!0,allowUnknownNamedParameters:this.#n.allowUnknownNamedParameters??!1};try{return o._create(this.#e,this.#e.prepare(e),e,r)}catch(e){throw i(e)}}location(e){if(this.#i(),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()}#i(){if(!this.isOpen)throw new n(`database is not open`)}#a(){let e=this.#e;this.#n.enableForeignKeyConstraints===!1?e.exec(`PRAGMA foreign_keys = OFF`):e.exec(`PRAGMA foreign_keys = ON`),this.#n.timeout!==void 0&&this.#n.timeout>0&&e.exec(`PRAGMA busy_timeout = ${this.#n.timeout}`)}};DatabaseSync.prototype.exec=DatabaseSync.prototype.sqlExec;export{DatabaseSync};
package/lib/esm/errors.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";var SqliteError=class extends Error{code=`ERR_SQLITE_ERROR`;errcode;errstr;constructor(e,t=0,n=``){super(e),this.name=`SqliteError`,this.errcode=t,this.errstr=n||e}},InvalidStateError=class extends Error{code=`ERR_INVALID_STATE`;constructor(e){super(e),this.name=`InvalidStateError`}},InvalidArgTypeError=class extends TypeError{code=`ERR_INVALID_ARG_TYPE`;constructor(e){super(e),this.name=`InvalidArgTypeError`}},InvalidArgValueError=class extends Error{code=`ERR_INVALID_ARG_VALUE`;constructor(e){super(e),this.name=`InvalidArgValueError`}},OutOfRangeError=class extends RangeError{code=`ERR_OUT_OF_RANGE`;constructor(e){super(e),this.name=`OutOfRangeError`}},ConstructCallRequiredError=class extends TypeError{code=`ERR_CONSTRUCT_CALL_REQUIRED`;constructor(e){super(`Cannot call constructor without \`new\`: ${e}`),this.name=`ConstructCallRequiredError`}},InvalidUrlSchemeError=class extends TypeError{code=`ERR_INVALID_URL_SCHEME`;constructor(e=`The URL must be of scheme file:`){super(e),this.name=`InvalidUrlSchemeError`}},IllegalConstructorError=class extends TypeError{code=`ERR_ILLEGAL_CONSTRUCTOR`;constructor(){super(`Illegal constructor`),this.name=`IllegalConstructorError`}};function isNodeSqliteError(e){return e instanceof SqliteError||e instanceof InvalidStateError||e instanceof InvalidArgTypeError||e instanceof InvalidArgValueError||e instanceof OutOfRangeError||e instanceof ConstructCallRequiredError||e instanceof InvalidUrlSchemeError||e instanceof IllegalConstructorError}function sqliteErrorMessage(e){let t=e?.message;return typeof t==`string`?t:String(e)}export{ConstructCallRequiredError,IllegalConstructorError,InvalidArgTypeError,InvalidArgValueError,InvalidStateError,InvalidUrlSchemeError,OutOfRangeError,SqliteError,isNodeSqliteError,sqliteErrorMessage};
1
+ import"./_virtual/_rolldown/runtime.js";var SqliteError=class extends Error{code=`ERR_SQLITE_ERROR`;errcode;errstr;constructor(e,t=0,n=``){super(e),this.name=`SqliteError`,this.errcode=t,this.errstr=n||e}},InvalidStateError=class extends Error{code=`ERR_INVALID_STATE`;constructor(e){super(e),this.name=`InvalidStateError`}},InvalidArgTypeError=class extends TypeError{code=`ERR_INVALID_ARG_TYPE`;constructor(e){super(e),this.name=`InvalidArgTypeError`}},InvalidArgValueError=class extends Error{code=`ERR_INVALID_ARG_VALUE`;constructor(e){super(e),this.name=`InvalidArgValueError`}},OutOfRangeError=class extends RangeError{code=`ERR_OUT_OF_RANGE`;constructor(e){super(e),this.name=`OutOfRangeError`}},ConstructCallRequiredError=class extends TypeError{code=`ERR_CONSTRUCT_CALL_REQUIRED`;constructor(e){super(`Cannot call constructor without \`new\`: ${e}`),this.name=`ConstructCallRequiredError`}},InvalidUrlSchemeError=class extends TypeError{code=`ERR_INVALID_URL_SCHEME`;constructor(e=`The URL must be of scheme file:`){super(e),this.name=`InvalidUrlSchemeError`}},IllegalConstructorError=class extends TypeError{code=`ERR_ILLEGAL_CONSTRUCTOR`;constructor(){super(`Illegal constructor`),this.name=`IllegalConstructorError`}};function isNodeSqliteError(e){return e instanceof SqliteError||e instanceof InvalidStateError||e instanceof InvalidArgTypeError||e instanceof InvalidArgValueError||e instanceof OutOfRangeError||e instanceof ConstructCallRequiredError||e instanceof InvalidUrlSchemeError||e instanceof IllegalConstructorError}function sqliteErrorMessage(e){let t=e?.message;return typeof t==`string`?t:String(e)}function sqliteErrorCode(e){let t=e?.code;return typeof t==`number`?t:0}function toSqliteError(e){return isNodeSqliteError(e)?e:new SqliteError(sqliteErrorMessage(e),sqliteErrorCode(e))}export{ConstructCallRequiredError,IllegalConstructorError,InvalidArgTypeError,InvalidArgValueError,InvalidStateError,InvalidUrlSchemeError,OutOfRangeError,SqliteError,isNodeSqliteError,sqliteErrorCode,sqliteErrorMessage,toSqliteError};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{InvalidStateError as e}from"./errors.js";import{getLoadError as t,loadNativeSqlite as n}from"@gjsify/sqlite-native";function nativeSqlite(){let r=n();if(!r){let n=t()?.message;throw new e(`@gjsify/sqlite requires the @gjsify/sqlite-native prebuild for this platform${n?`: ${n}`:``}`)}return r}export{nativeSqlite};
@@ -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{ColumnTypes as o,executeStatement as s,integerColumns as c,releaseStatement as l}from"./execution.js";import{parseSql as u}from"./parse-sql.js";import{readAllRows as d,readFirstRow as f}from"./data-model-reader.js";import{convertParameterSyntax as p}from"./parameter-syntax.js";import{rewriteExistsSubqueries as m}from"./exists-subquery.js";import{providerSql as h,statementKind as g}from"./statement-kind.js";import{bindHolders as _,releaseHolders as v}from"./param-binding.js";const y=Symbol(`StatementSync.internal`),b=`SELECT changes(), last_insert_rowid()`,x=c(2),S=new WeakMap;function counterStatement(e){let t=S.get(e);if(t)return t;let[n]=u(e,b);return S.set(e,n),n}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 holderBinding(e){if(typeof e==`string`)return{type:`gchararray`,value:e};if(typeof e==`number`)return{type:`gdouble`,value:e};if(typeof e==`bigint`){if(e>9223372036854775807n||e<-9223372036854775808n)throw new n(`BigInt value is too large to bind.`);return{type:`gint64`,value:e}}return typeof e==`boolean`?{type:`gint64`,value:+!!e}:null}function sqlLiteral(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 C=class StatementSync{#e;#t;#n;#r;#i;#a;#o;#s=new o;#c;#l=new Map;constructor(t,n,r,i,a){if(t!==y)throw new e;this.#e=n,this.#t=r,this.#n=a,this.#c=g(r),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(y,e,t,n,r)}get sourceSQL(){return this.#t}get expandedSQL(){return this.#t}#u(e){return{readBigInts:this.#r,returnArrays:this.#i,textColumns:e}}#d(){let e=-1;for(let t of this.#n)t.position>e&&(e=t.position);return e}#f(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,bindings: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.#d())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.#d()+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]=p(this.#t,e=>{let n=a.get(e.gdaId),r=holderBinding(n);return r?(t.set(e.gdaId,r),`##${e.gdaId}::${r.type}`):sqlLiteral(n)});return{sql:o,bindings:t}}#p(e){let t=this.#l.get(e);if(t)return this.#l.delete(e),this.#l.set(e,t),t;let n=u(this.#e,h(m(e),this.#c));for(this.#l.set(e,n);this.#l.size>8;){let[e,[t]]=this.#l.entries().next().value;this.#l.delete(e),l(this.#e,t)}return n}#m(e,t,n){let{sql:o,bindings:c}=this.#f(e),l=null;try{let e;return[e,l]=this.#p(o),_(l,c),s(this.#e,e,l,t,{columns:n,retain:!0,kind:this.#c})}catch(e){throw i(e)?e:new r(a(e))}finally{v(l,c)}}run(...e){this.#m(e,()=>void 0);let[t,n]=s(this.#e,counterStatement(this.#e),null,e=>{if(!e||e.get_n_rows()===0)throw new r(`${b} returned no row`);return[BigInt(e.get_value_at(0,0)),BigInt(e.get_value_at(1,0))]},{columns:x,retain:!0});return this.#r?{changes:t,lastInsertRowid:n}:{changes:Number(t),lastInsertRowid:Number(n)}}get(...e){return this.#m(e,(e,t)=>{if(!(!e||e.get_n_rows()===0))return f(e,this.#u(t))},this.#s)}all(...e){return this.#m(e,(e,t)=>e?d(e,this.#u(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{C as StatementSync};
1
+ import"./_virtual/_rolldown/runtime.js";import{IllegalConstructorError as e,InvalidArgTypeError as t,InvalidArgValueError as n,InvalidStateError as r,OutOfRangeError as i,SqliteError as a,toSqliteError as o}from"./errors.js";import{nativeSqlite as s}from"./native.js";const c=Symbol(`StatementSync.internal`),l=`SELECT last_insert_rowid()`,u=new WeakMap;function rowidStatement(e){let t=u.get(e);return t||(t=e.prepare(l),u.set(e,t)),t}function isNamedArgObject(e){return typeof e==`object`&&!!e&&!ArrayBuffer.isView(e)}function viewBytes(e){return e instanceof Uint8Array?e:new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}function iteratorPrototype(){let e=globalThis.Iterator;return e?e.prototype:null}var d=class StatementSync{#e;#t;#n;#r;#i;#a;#o;#s=null;#c=0;constructor(t,n,r,i,a){if(t!==c)throw new e;this.#e=n,this.#t=r,this.#n=i,this.#r=a.readBigInts??!1,this.#i=a.returnArrays??!1,this.#a=a.allowBareNamedParameters??!0,this.#o=a.allowUnknownNamedParameters??!1}static _create(e,t,n,r){return new StatementSync(c,e,t,n,r)}get sourceSQL(){return this.#n}get expandedSQL(){return this.#t.expanded_sql??this.#n}run(...e){this.#l();try{this.#u(),this.#d(e),this.#t.step()}catch(e){throw this.#u(),o(e)}this.#u();let t=this.#e.changes;return this.#r?{changes:BigInt(t),lastInsertRowid:this.#v()}:{changes:t,lastInsertRowid:this.#e.last_insert_rowid}}get(...e){let{StepResult:t}=s();this.#l();try{return this.#u(),this.#d(e),this.#t.step()!==t.ROW||this.#t.column_count===0?void 0:this.#h(this.#i?null:this.#m())}catch(e){throw o(e)}finally{this.#u()}}all(...e){let{StepResult:t}=s();this.#l();let n=[];try{this.#u(),this.#d(e);let r=this.#i?null:this.#m();for(;this.#t.step()===t.ROW;)n.push(this.#h(r))}catch(e){throw o(e)}finally{this.#u()}return n}iterate(...e){let{StepResult:t}=s();this.#l();try{this.#u(),this.#d(e)}catch(e){throw this.#u(),o(e)}let n=this.#m(),i=this.#c,a=!1,stop=()=>(a||(a=!0,this.#c===i&&this.#u()),{done:!0,value:null}),c={next:()=>{if(a)return{done:!0,value:null};if(this.#c!==i)throw new r(`iterator was invalidated`);this.#l();let e;try{e=this.#t.step()}catch(e){throw a=!0,this.#u(),o(e)}return e===t.ROW?{done:!1,value:this.#h(this.#i?null:n)}:stop()},return:stop,[Symbol.iterator]:()=>c},l=iteratorPrototype();return l&&Object.setPrototypeOf(c,l),c}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}#l(){if(!this.#t.is_valid)throw new r(`statement has been finalized`)}#u(){this.#c++,this.#t.reset()}#d(e){let t=this.#t;t.clear_bindings();let n=1,i=0;if(e.length>0&&isNamedArgObject(e[0])){let n=e[0];for(let e of Object.keys(n)){let i=t.bind_parameter_index(e);if(i===0&&this.#a&&(i=this.#f(e)),i===0){if(this.#o)continue;throw new r(`Unknown named parameter '${e}'`)}this.#p(n[e],i)}i++}for(let r=i;r<e.length;r++){for(;;){let e=t.bind_parameter_name(n);if(e===null||e[0]===`?`)break;n++}this.#p(e[r],n),n++}}#f(e){let t=this.#s;if(!t){t=new Map;let e=this.#t,n=e.bind_parameter_count;for(let i=1;i<=n;i++){let n=e.bind_parameter_name(i);if(n===null)continue;let a=n.slice(1),o=t.get(a);if(o!==void 0){if(o===n)continue;throw new r(`Cannot create bare named parameter '${a}' because of conflicting names '${o}' and '${n}'.`)}t.set(a,n)}this.#s=t}let n=t.get(e);return n===void 0?0:this.#t.bind_parameter_index(n)}#p(e,r){let i=this.#t;if(typeof e==`number`)i.bind_double(r,e);else if(typeof e==`string`)i.bind_text(r,e);else if(e==null)i.bind_null(r);else if(ArrayBuffer.isView(e))i.bind_blob(r,viewBytes(e));else if(typeof e==`bigint`){if(e>9223372036854775807n||e<-9223372036854775808n)throw new n(`BigInt value is too large to bind.`);i.bind_int64(r,e)}else if(typeof e==`boolean`)i.bind_int64(r,e?1n:0n);else throw new t(`Provided value cannot be bound to SQLite parameter ${r}.`)}#m(){let e=this.#t,t=e.column_count;return Array.from({length:t},(t,n)=>e.column_name(n)??``)}#h(e){let{ColumnType:t}=s();if(e===null){let e=this.#t.column_count;return Array.from({length:e},(e,n)=>this.#g(t,n))}let n=Object.create(null);for(let r=0;r<e.length;r++)n[e[r]]=this.#g(t,r);return n}#g(e,t){let n=this.#t;switch(n.column_type(t)){case e.NULL:return null;case e.FLOAT:return n.column_double(t);case e.TEXT:return n.column_text(t)??``;case e.BLOB:return new Uint8Array(n.column_blob(t).get_data()??[]);default:return this.#_(t)}}#_(e){let t=this.#t.column_double(e);if(Number.isSafeInteger(t))return this.#r?BigInt(t):t;let n=this.#t.column_text(e)??`0`;if(this.#r)return BigInt(n);throw new i(`Value is too large to be represented as a JavaScript number: ${n}`)}#v(){let{StepResult:e}=s(),t=rowidStatement(this.#e);try{if(t.step()!==e.ROW)throw new a(`${l} returned no row`);return BigInt(t.column_text(0)??`0`)}finally{t.reset()}}};export{d as StatementSync};
@@ -5,6 +5,14 @@ export declare class DatabaseSync {
5
5
  constructor(path: unknown, options?: unknown);
6
6
  get [sqliteTypeSymbol](): string;
7
7
  get isOpen(): boolean;
8
+ /**
9
+ * Whether a transaction is open — asked of SQLite, never read off the SQL.
10
+ *
11
+ * The text cannot answer it: `CREATE TRIGGER … BEGIN … END` carries the word BEGIN
12
+ * and opens no transaction, while `SAVEPOINT`/`RELEASE` open and close one and carry
13
+ * neither word. The native property is `sqlite3_get_autocommit()`, which is what
14
+ * node:sqlite reads too — so both cases now agree with it.
15
+ */
8
16
  get isTransaction(): boolean;
9
17
  open(): undefined;
10
18
  close(): undefined;
@@ -34,9 +34,9 @@ export declare class IllegalConstructorError extends TypeError {
34
34
  }
35
35
  /**
36
36
  * Whether `cause` is one of the errors above — already Node-shaped, so a catch that
37
- * translates libgda's must let it through untouched.
37
+ * translates the native module's must let it through untouched.
38
38
  *
39
- * **The discriminator cannot be `instanceof Error`.** libgda reports through
39
+ * **The discriminator cannot be `instanceof Error`.** The native module reports through
40
40
  * `GLib.Error`, which is a boxed GObject value whose prototype chain does NOT reach
41
41
  * `Error.prototype` — on GJS and, since the GError identity fix, on `@gjsify/node-gi`
42
42
  * too. It used to be a real `Error` subclass there, so an `instanceof Error` test
@@ -45,13 +45,29 @@ export declare class IllegalConstructorError extends TypeError {
45
45
  */
46
46
  export declare function isNodeSqliteError(cause: unknown): boolean;
47
47
  /**
48
- * The message libgda actually reported.
48
+ * The message SQLite actually reported.
49
49
  *
50
50
  * An `e instanceof Error ? e.message : String(e)` extraction takes the `String(e)`
51
51
  * branch for a GJS `GLib.Error` and yields
52
- * `"GLib.Error gda_server_provider_error: no such table: t"`; under node-gi the same
52
+ * `"GLib.Error gjsify-sqlite-error: no such table: t"`; under node-gi the same
53
53
  * expression takes the OTHER branch and yields the bare message. The `message`
54
54
  * property alone is SQLite's own text on both — byte-for-byte what node:sqlite
55
55
  * reports for the same statement — so read the property instead of stringifying.
56
56
  */
57
57
  export declare function sqliteErrorMessage(cause: unknown): string;
58
+ /**
59
+ * SQLite's result code for a failure the native module raised.
60
+ *
61
+ * `GjsifySqlite.SqliteError` is a GError domain whose `code` IS the extended result
62
+ * code, which is exactly what node:sqlite exposes as `err.errcode`. Anything else
63
+ * reports 0 rather than a number from an unrelated domain.
64
+ */
65
+ export declare function sqliteErrorCode(cause: unknown): number;
66
+ /**
67
+ * A native failure in the shape a consumer written against node:sqlite branches on.
68
+ *
69
+ * Returned rather than thrown, so every call site reads `throw toSqliteError(e)` and
70
+ * stays an exit the type checker can see. One of our own errors passes through: it is
71
+ * already the shape, and re-wrapping would lose its `code`.
72
+ */
73
+ export declare function toSqliteError(cause: unknown): Error;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,11 @@
1
+ import { type NativeSqliteModule } from '@gjsify/sqlite-native';
2
+ /**
3
+ * The loaded native module, or a thrown explanation of why there is none.
4
+ *
5
+ * Unlike `@gjsify/tty`, which degrades to an env/GLib reading of the terminal when
6
+ * `@gjsify/terminal-native` is absent, there is no second engine to fall back to: the
7
+ * prebuild IS SQLite here. So the failure is raised at the first call that needs it —
8
+ * carrying the loader's own message, which names the missing library rather than only
9
+ * the namespace.
10
+ */
11
+ export declare function nativeSqlite(): NativeSqliteModule;
@@ -1,16 +1,25 @@
1
- import type Gda from '@girs/gda-6.0';
2
- import { type ParamInfo } from './parameter-syntax.ts';
3
- import type { RunResult, StatementSyncOptions } from './types.ts';
1
+ import type { Database as NativeDatabase, Statement as NativeStatement } from '@gjsify/sqlite-native';
2
+ import type { RunResult, StatementIterator, StatementRow, StatementSyncOptions } from './types.ts';
4
3
  export declare class StatementSync {
5
4
  #private;
6
- constructor(sentinel: symbol, connection: Gda.Connection, sql: string, options: StatementSyncOptions, paramMap: ParamInfo[]);
5
+ constructor(sentinel: symbol, database: NativeDatabase, statement: NativeStatement, sql: string, options: StatementSyncOptions);
7
6
  /** @internal */
8
- static _create(connection: Gda.Connection, sql: string, options: StatementSyncOptions, paramMap: ParamInfo[]): StatementSync;
7
+ static _create(database: NativeDatabase, statement: NativeStatement, sql: string, options: StatementSyncOptions): StatementSync;
9
8
  get sourceSQL(): string;
10
9
  get expandedSQL(): string;
11
10
  run(...args: unknown[]): RunResult;
12
- get(...args: unknown[]): Record<string, unknown> | unknown[] | undefined;
13
- all(...args: unknown[]): (Record<string, unknown> | unknown[])[];
11
+ get(...args: unknown[]): StatementRow | undefined;
12
+ all(...args: unknown[]): StatementRow[];
13
+ /**
14
+ * Step the statement one row at a time.
15
+ *
16
+ * Nothing is read until `next()` asks, which is the whole point: `all()` materialises
17
+ * every row before the caller sees the first one, and a table of BLOBs does not fit
18
+ * twice. The statement is reset when the rows run out and when a loop is left early
19
+ * (`break`, `return`, a throw) — the latter through the iterator protocol's own
20
+ * `return()`, which `for…of` calls for exactly this.
21
+ */
22
+ iterate(...args: unknown[]): StatementIterator;
14
23
  setReadBigInts(enabled: unknown): undefined;
15
24
  setReturnArrays(enabled: unknown): undefined;
16
25
  setAllowBareNamedParameters(enabled: unknown): undefined;
@@ -29,3 +29,16 @@ export interface ColumnInfo {
29
29
  type: string | null;
30
30
  }
31
31
  export type SQLiteValue = null | number | bigint | string | Uint8Array;
32
+ /** One result row, an object by default and an array under `returnArrays`. */
33
+ export type StatementRow = Record<string, unknown> | unknown[];
34
+ /**
35
+ * What `StatementSync.iterate()` hands back.
36
+ *
37
+ * An iterator AND an iterable — `for…of` needs the second — whose `return()` is
38
+ * declared because the contract includes resetting the statement when a loop is left
39
+ * early, not only when it runs out.
40
+ */
41
+ export interface StatementIterator extends Iterator<StatementRow, null> {
42
+ [Symbol.iterator](): StatementIterator;
43
+ return(): IteratorResult<StatementRow, null>;
44
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gjsify/sqlite",
3
- "version": "0.64.12-next.280",
4
- "description": "Node.js sqlite module for Gjs using libgda",
3
+ "version": "0.64.12",
4
+ "description": "Node.js sqlite module for Gjs",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
7
7
  "types": "lib/types/index.d.ts",
@@ -31,27 +31,24 @@
31
31
  "test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:node && gjsify run test:gjs",
32
32
  "test:gjs": "gjsify run test.gjs.mjs",
33
33
  "test:node": "node test.node.mjs",
34
- "test:gjs-on-node": "gjsify build src/test.node-gi.mts --app node --alias node:sqlite=@gjsify/sqlite --outfile dist/test.node-gi.mjs && node dist/test.node-gi.mjs"
34
+ "test:gjs-on-node": "gjsify build src/test.node-gi.mts --app node --alias node:sqlite=@gjsify/sqlite --outfile dist/test.node-gi.mjs && gjsify run --runtime node dist/test.node-gi.mjs"
35
35
  },
36
36
  "keywords": [
37
37
  "gjs",
38
38
  "node",
39
39
  "sqlite",
40
- "libgda"
40
+ "sqlite3"
41
41
  ],
42
42
  "devDependencies": {
43
- "@gjsify/cli": "0.64.12-next.280",
43
+ "@gjsify/cli": "^0.64.12",
44
44
  "@gjsify/node-gi": "file:../../../packages/node-gi/node-gi",
45
- "@gjsify/unit": "0.64.12-next.280",
45
+ "@gjsify/unit": "^0.64.12",
46
46
  "@types/node": "^25.9.2",
47
47
  "typescript": "^6.0.3"
48
48
  },
49
49
  "dependencies": {
50
- "@girs/gda-6.0": "5.4.0",
51
- "@girs/gio-2.0": "5.4.0",
52
50
  "@girs/glib-2.0": "5.4.0",
53
- "@girs/gobject-2.0": "5.4.0",
54
- "@gjsify/utils": "0.64.12-next.280"
51
+ "@gjsify/sqlite-native": "^0.64.12"
55
52
  },
56
53
  "gjsify": {
57
54
  "runtimes": {
@@ -71,6 +68,5 @@
71
68
  "bugs": {
72
69
  "url": "https://github.com/gjsify/gjsify/issues"
73
70
  },
74
- "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/node/sqlite#readme",
75
- "gitHead": "0a9185d91127072fce6aa54dc126e87e6ecd0c3d"
71
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/node/sqlite#readme"
76
72
  }
@@ -1,2 +0,0 @@
1
- import"./_virtual/_rolldown/runtime.js";import{executeStatement as e,integerColumns as t,releaseRetained as n}from"./execution.js";import{parseSql as r}from"./parse-sql.js";import i from"@girs/gio-2.0";const a=new Set,o=new Map;function keyOf(e){return`${e.readOnly?`ro`:`rw`}\u0000${e.path}`}function fileIdentity(e){let t=i.File.new_for_path(e);try{return t.query_info(i.FILE_ATTRIBUTE_ID_FILE,i.FileQueryInfoFlags.NONE,null).get_attribute_string(i.FILE_ATTRIBUTE_ID_FILE)}catch{return null}}function exec(t,n){let[i]=r(t,n);e(t,i,null,()=>void 0)}function query(n,i,a){let[o]=r(n,i);return e(n,o,null,e=>{if(!e)return[];let t=[];for(let n=0;n<e.get_n_rows();n++){let r=[];for(let t=0;t<e.get_n_columns();t++)r.push(String(e.get_value_at(t,n)));t.push(r)}return t},{columns:t(a)})}const s={table:`TABLE`,view:`VIEW`,index:`INDEX`,trigger:`TRIGGER`};function userObjects(e,t){return query(e,`SELECT type, name FROM ${t} WHERE name NOT LIKE 'sqlite_%'
2
- ORDER BY CASE type WHEN 'trigger' THEN 0 WHEN 'view' THEN 1 WHEN 'index' THEN 2 ELSE 3 END`,2)}function wipeMemory(e){for(let t of[`sqlite_master`,`sqlite_temp_master`])for(;;){let n=userObjects(e,t);if(n.length===0)break;let r=0;for(let[t,i]of n){let n=s[t];if(n)try{exec(e,`DROP ${n} IF EXISTS "${i.replace(/"/g,`""`)}"`),r++}catch{}}if(r===0)break}exec(e,`PRAGMA user_version = 0`),exec(e,`PRAGMA application_id = 0`)}function isPristine(e){for(let t of[`sqlite_master`,`sqlite_temp_master`])if(query(e,`SELECT name FROM ${t}`,1).length>0)return!1;for(let t of[`pragma_user_version()`,`pragma_application_id()`]){let[n]=query(e,`SELECT * FROM ${t}`,1);if(!n||n[0]!==`0`)return!1}return!0}function rollbackIfNeeded(e){e.get_transaction_status()&&exec(e,`ROLLBACK`)}function acquire(e,t){let n=o.get(keyOf(e)),r=e.isMemory?null:fileIdentity(e.path);for(;n&&n.length>0;){let t=n.pop();if(e.isMemory||r!==null&&t.fileId===r)return t.connection}let i=t();return a.add(i),i}function release(e,t){try{if(n(t),rollbackIfNeeded(t),e.isMemory&&(wipeMemory(t),!isPristine(t)))return;let r=keyOf(e),i=o.get(r)??[];i.push({connection:t,fileId:e.isMemory?null:fileIdentity(e.path)}),o.set(r,i)}catch{}}export{acquire,release};
@@ -1 +0,0 @@
1
- import"./_virtual/_rolldown/runtime.js";import{OutOfRangeError as e,SqliteError as t}from"./errors.js";const n=BigInt(2**53-1),r=/^[+-]?\d+$/;function convertIntegerText(t,i){if(r.test(t)){let r=BigInt(t);if(i)return r;if(r>n||r<-n)throw new e(`Value is too large to be represented as a JavaScript number: ${r}`);return Number(r)}let a=Number(t);return t.trim()!==``&&Number.isFinite(a)?a:t}function decodeBinaryString(e,n){let r=new Uint8Array(n),i=e.length,a=0,o=0;for(;o<i;){if(a>=n)throw new t(`BLOB decoded to more than ${n} bytes`);let i=e.charCodeAt(o);if(i!==92){if(i>127)throw new t(`BLOB holds a non-ASCII character at offset ${o}`);r[a++]=i,o+=1;continue}let s=e.charCodeAt(o+1)-48;if(s===44){r[a++]=92,o+=2;continue}let c=e.charCodeAt(o+2)-48,l=e.charCodeAt(o+3)-48;if(!(s>=0&&s<=3&&c>=0&&c<=7&&l>=0&&l<=7))throw new t(`BLOB holds an unknown escape at offset ${o}`);r[a++]=s<<6|c<<3|l,o+=4}if(a!==n)throw new t(`BLOB decoded to ${a} bytes, expected ${n}`);return r}function readBinary(e){return decodeBinaryString(e.to_string(0),e.get_size())}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.get_size==`function`&&typeof i.to_string==`function`?readBinary(i):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 +0,0 @@
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))}const a=new Map;function retainPrepared(e,t){for(a.delete(t),a.set(t,e);a.size>512;){let[e,t]=a.entries().next().value;a.delete(e),t.del_prepared_statement(e)}}function releaseStatement(e,t){a.delete(t),e.del_prepared_statement(t)}function releaseRetained(e){for(let[t,n]of a)n===e&&releaseStatement(e,t)}function executeStatement(e,t,n,r,i={}){let a=i.columns,o=null,s=!1;try{o=execute(e,t,n,a,i.kind),o&&assertTyped(o);let c=r(o,a?.textColumns??[]);return s=!isForwardCursor(t,o,a,i.kind),c}finally{o&&(s&&i.retain&&o.get_n_rows(),releasePreparedStatement(o)),s&&i.retain?retainPrepared(e,t):releaseStatement(e,t)}}function returnsRows(e,n){let r=e.get_statement_type();return r===t.SqlStatementType.SELECT?!0:r===t.SqlStatementType.UNKNOWN?n===`rows`:!1}function isForwardCursor(e,t,n,r){return t!==null&&n===void 0&&returnsRows(e,r)}function execute(e,n,r,i,a){if(returnsRows(n,a))return i?executeTyped(e,n,r,i):e.statement_execute_select_full(n,r,t.StatementModelUsage.CURSOR_FORWARD,null);let o=t.Batch.new();o.add_statement(n);let[s]=e.batch_execute(o,r,t.StatementModelUsage.RANDOM_ACCESS);return!s||s instanceof t.Set?null:s}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),releaseStatement(t,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),releaseStatement(e,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,releaseRetained,releaseStatement};
@@ -1 +0,0 @@
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};
@@ -1 +0,0 @@
1
- import"./_virtual/_rolldown/runtime.js";import{SqliteError as e}from"./errors.js";function setHolderValue(e,t){return e.set_value(t)}function releaseHolders(e,t){if(e)for(let[n,r]of t)r.type===`gchararray`&&e.get_holder(n)?.set_value(``)}function bindHolders(t,n){if(n.size!==0){if(!t)throw new e(`Failed to bind parameters: statement has no parameter set`);for(let[r,i]of n){let n=t.get_holder(r);if(!n)throw new e(`Failed to bind parameter '${r}'`);setHolderValue(n,i.value)}}}export{bindHolders,releaseHolders};
@@ -1 +0,0 @@
1
- import"./_virtual/_rolldown/runtime.js";const asStringHolder=e=>`##${e.gdaId}::string`;function convertParameterSyntax(e,t=asStringHolder){let n=[],r=0,i=``,a=0;for(;a<e.length;){if(e[a]===`'`){let t=a;for(a++;a<e.length&&e[a]!==`'`;){if(e[a]===`'`&&e[a+1]===`'`){a+=2;continue}a++}a<e.length&&a++,i+=e.substring(t,a);continue}if(e[a]===`?`){a++;let o=``;for(;a<e.length&&e[a]>=`0`&&e[a]<=`9`;)o+=e[a],a++;let s=o?parseInt(o,10)-1:r;r=o?r:r+1;let c={gdaId:`p${s}`,originalName:o?`?${o}`:`?`,position:s};n.push(c),i+=t(c);continue}if((e[a]===`$`||e[a]===`:`||e[a]===`@`)&&a+1<e.length&&/[a-zA-Z_]/.test(e[a+1])){let r=e[a];a++;let o=``;for(;a<e.length&&/[a-zA-Z0-9_]/.test(e[a]);)o+=e[a],a++;let s={gdaId:o,originalName:`${r}${o}`,position:-1};n.push(s),i+=t(s);continue}i+=e[a],a++}return[i,n]}export{asStringHolder,convertParameterSyntax};
@@ -1 +0,0 @@
1
- import"./_virtual/_rolldown/runtime.js";import{SqliteError as e}from"./errors.js";function parseSql(t,n){let[r,i]=t.parse_sql_string(n);if(!r)throw new e(`Failed to parse SQL statement`);return[r,i]}export{parseSql};
@@ -1,2 +0,0 @@
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 +0,0 @@
1
- import"./_virtual/_rolldown/runtime.js";import{sqlRegions as e}from"./sql-regions.js";const t=new Set([`SELECT`,`VALUES`]),n=new Set([`INSERT`,`UPDATE`,`DELETE`,`REPLACE`]);function statementKind(e){let r=tokenize(e),i=r[0];if(!i||i.kind!==`word`)return`other`;let a=i.text.toUpperCase()===`WITH`?verbAfterCtes(r):i.text.toUpperCase();return a===null?`other`:t.has(a)?`rows`:n.has(a)?`write`:`other`}function providerSql(e,t){if(t!==`rows`)return e;let n=tokenize(e)[0];if(n&&n.kind===`word`&&n.text.toUpperCase()===`SELECT`)return e;let r=splitTrailingSemicolon(e);return`SELECT * FROM (${endsInsideLineComment(r.body)?`${r.body}\n`:r.body})${r.tail}`}function verbAfterCtes(e){let t=1;for(isWord(e[t],`RECURSIVE`)&&t++;;){if(!e[t]||e[t].kind!==`word`&&e[t].kind!==`quoted`)return null;if(t++,isPunct(e[t],`(`)){let n=matchingParen(e,t);if(n<0)return null;t=n+1}if(!isWord(e[t],`AS`)||(t++,isWord(e[t],`NOT`)&&t++,isWord(e[t],`MATERIALIZED`)&&t++,!isPunct(e[t],`(`)))return null;let n=matchingParen(e,t);if(n<0)return null;if(t=n+1,isPunct(e[t],`,`)){t++;continue}let r=e[t];return r&&r.kind===`word`?r.text.toUpperCase():null}}function matchingParen(e,t){let n=0;for(let r=t;r<e.length;r++)if(e[r].kind===`punct`){if(e[r].text===`(`)n++;else if(e[r].text===`)`&&--n===0)return r}return-1}function isWord(e,t){return e!==void 0&&e.kind===`word`&&e.text.toUpperCase()===t}function isPunct(e,t){return e!==void 0&&e.kind===`punct`&&e.text===t}function splitTrailingSemicolon(t){let n=e(t),r=-1;for(let e of n)if(e.kind===`code`)for(let n=e.start;n<e.end;n++)t[n]===`;`&&(r=n);if(r<0)return{body:t,tail:``};for(let e of n){let n=Math.max(e.start,r+1);if(!(n>=e.end)){if(e.kind===`code`){if(t.slice(n,e.end).trim()!==``)return{body:t,tail:``}}else if(e.kind===`quoted`)return{body:t,tail:``}}}return{body:t.slice(0,r),tail:t.slice(r)}}function endsInsideLineComment(t){let n=e(t),r=n[n.length-1];return r!==void 0&&r.kind===`line-comment`&&r.end===t.length}function tokenize(t){let n=[];for(let r of e(t)){if(r.kind===`quoted`){n.push({kind:`quoted`,text:t.slice(r.start,r.end)});continue}if(r.kind!==`code`)continue;let e=r.start;for(;e<r.end;){let i=t[e];if(isSpace(i)){e++;continue}if(i===`#`&&t[e+1]===`#`){let i=placeholderEnd(t,e,r.end);n.push({kind:`param`,text:t.slice(e,i)}),e=i;continue}if(i===`?`){let i=e+1;for(;i<r.end&&t[i]>=`0`&&t[i]<=`9`;)i++;n.push({kind:`param`,text:t.slice(e,i)}),e=i;continue}if((i===`:`||i===`$`||i===`@`)&&isNameStart(t[e+1])){let i=e+1;for(;i<r.end&&isNamePart(t[i]);)i++;n.push({kind:`param`,text:t.slice(e,i)}),e=i;continue}if(isNameStart(i)){let i=e+1;for(;i<r.end&&isNamePart(t[i]);)i++;n.push({kind:`word`,text:t.slice(e,i)}),e=i;continue}n.push({kind:`punct`,text:i}),e++}}return n}function placeholderEnd(e,t,n){let r=t+2;for(;r<n&&isNamePart(e[r]);)r++;if(e[r]===`:`&&e[r+1]===`:`)for(r+=2;r<n&&isNamePart(e[r]);)r++;return r}function isSpace(e){return e!==void 0&&/\s/.test(e)}function isNameStart(e){return e!==void 0&&/[A-Za-z_]/.test(e)}function isNamePart(e){return e!==void 0&&/[A-Za-z0-9_$]/.test(e)}export{providerSql,statementKind};
@@ -1,24 +0,0 @@
1
- import type Gda from '@girs/gda-6.0';
2
- export interface PoolKey {
3
- /** The database path as the caller gave it — `:memory:` or a file path. */
4
- path: string;
5
- isMemory: boolean;
6
- readOnly: boolean;
7
- }
8
- /**
9
- * A connection for `key` — a parked one proven equivalent to a fresh one, or a new one
10
- * from `create`.
11
- *
12
- * The caller's `create` is what knows the connection string; this module only owns the
13
- * lifetime. A connection it returns is registered before it is handed out, so even a
14
- * caller that drops it on the floor cannot let the garbage collector finalize it.
15
- */
16
- export declare function acquire(key: PoolKey, create: () => Gda.Connection): Gda.Connection;
17
- /**
18
- * Take a connection back from a `DatabaseSync` that is done with it.
19
- *
20
- * Never closes it (see the note at the top of this file). A `:memory:` connection is
21
- * wiped and parked only if it verifies as pristine afterwards; a file connection is parked
22
- * with the identity of the file it is attached to.
23
- */
24
- export declare function release(key: PoolKey, connection: Gda.Connection): void;
@@ -1,10 +0,0 @@
1
- import type Gda from '@girs/gda-6.0';
2
- export interface ReadOptions {
3
- readBigInts: boolean;
4
- returnArrays: boolean;
5
- /** Per column: true where libgda was told to hand the value over as text (execution.ts). */
6
- textColumns?: boolean[];
7
- }
8
- export declare function readRow(model: Gda.DataModel, row: number, options: ReadOptions): Record<string, unknown> | unknown[] | undefined;
9
- export declare function readAllRows(model: Gda.DataModel, options: ReadOptions): (Record<string, unknown> | unknown[])[];
10
- export declare function readFirstRow(model: Gda.DataModel, options: ReadOptions): Record<string, unknown> | unknown[] | undefined;
@@ -1,99 +0,0 @@
1
- import Gda from '@girs/gda-6.0';
2
- import GObject from '@girs/gobject-2.0';
3
- import type { StatementKind } from './statement-kind.ts';
4
- /**
5
- * How the result columns of one prepared statement are read, remembered between its
6
- * executions.
7
- *
8
- * Learning it costs an extra execution (see `probeColumns`), so a `StatementSync` keeps one
9
- * of these for its lifetime. A column this has never seen typed (NULL in every probed row)
10
- * is left to libgda; if a later execution types it integer-like, it is probed again.
11
- */
12
- export declare class ColumnTypes {
13
- /** Per column: TYPE_STRING to read as exact text, GdaNull to let libgda decide. */
14
- types: GObject.GType[] | null;
15
- constructor(types?: GObject.GType[] | null);
16
- /** Which columns hold text that `data-model-reader.ts` must convert back. */
17
- get textColumns(): boolean[];
18
- }
19
- /** Every column read as text — for a query whose columns are all known to be integers. */
20
- export declare function integerColumns(count: number): ColumnTypes;
21
- /**
22
- * Drop the connection's prepared-statement cache entry for `stmt`.
23
- *
24
- * Call this when a statement is discarded rather than executed again — a reused one is
25
- * retained by `executeStatement` instead. It is also the remedy for a stale entry: a
26
- * retained `SELECT *` keeps the column count it was prepared with across an
27
- * `ALTER TABLE … ADD COLUMN`, and deleting the entry is what makes the next execution see
28
- * the new one (no reparse needed). `matches()` below is what notices.
29
- *
30
- * `del_prepared_statement()` does not check for a missing cache, which libgda creates on
31
- * the first successful prepare. open()'s first PRAGMA is always one, so every connection
32
- * this package hands out already has it.
33
- */
34
- export declare function releaseStatement(connection: Gda.Connection, stmt: Gda.Statement): void;
35
- /**
36
- * Give back every cache entry retained on `connection`.
37
- *
38
- * A `StatementSync` asks for retention and is then collected without telling anyone, so
39
- * the connection's own lifecycle is the only seam that can give its entries back — and it
40
- * must: a parked connection is handed to the NEXT consumer, who can recreate a table a
41
- * retained statement was compiled against. A never-closed `DatabaseSync` pins its
42
- * connection plus at most `MAX_RETAINED` compiled statements — bounded, by design.
43
- */
44
- export declare function releaseRetained(connection: Gda.Connection): void;
45
- export interface ExecuteOptions {
46
- /** How to read the result columns. Pass only when `read` reads rows. */
47
- columns?: ColumnTypes;
48
- /**
49
- * Keep the connection's prepared-statement cache entry when the execution leaves the
50
- * statement drained, so the next execution of the SAME `Gda.Statement` reuses the
51
- * compiled `sqlite3_stmt` (see `retained`). Only a caller that HOLDS its statement for
52
- * reuse asks for this; a one-shot statement would just occupy the bound.
53
- */
54
- retain?: boolean;
55
- /**
56
- * What the statement does, for the statements libgda cannot classify.
57
- *
58
- * A statement with a CTE reaches libgda as UNKNOWN whatever it does (see
59
- * `statement-kind.ts`), so the row-vs-rows decision cannot be left to
60
- * `get_statement_type()` alone — the answer comes from the SQL text instead. A
61
- * caller that does not know the statement leaves it out, and an UNKNOWN statement
62
- * then keeps the path it had.
63
- */
64
- kind?: StatementKind;
65
- }
66
- /**
67
- * Execute `stmt`, hand its result to `read`, and leave NOTHING behind on the connection.
68
- *
69
- * libgda keeps state per execution that only the connection's close() or the garbage
70
- * collector would otherwise release, and on a long-lived connection that state runs out:
71
- *
72
- * - The connection caches a prepared statement (`GdaSqlitePStmt`) for every
73
- * `Gda.Statement` it ever executed, holding a STRONG reference to both, until the
74
- * statement emits `reset` — which ours never do — or the connection closes. This package
75
- * renders a fresh statement per execution, so the cache grew by one on every call.
76
- * - Every `GdaSqlitePStmt` holds a GWeakRef to the SQLite provider, and GLib (≥ 2.84) caps
77
- * the GWeakRefs on one object at 65535. Past it, `g_weak_ref_set()` refuses with
78
- * "Too many GWeakRef registered", the next prepared statement has no provider, and
79
- * libgda answers `fuzzy_get_gtype: assertion 'prov != NULL' failed` — a CRITICAL, not an
80
- * error. Reads on that connection came back typeless or empty with no exception.
81
- * - A SELECT's data model (`GdaSqliteRecordset`) holds its prepared statement until the
82
- * model is finalized, and the model is a GJS wrapper the garbage collector frees
83
- * whenever it gets round to it. Measured: ~70,000 unread models outlive one GC.
84
- * - `statement_execute_non_select()` has a `last_insert_row` out-parameter. GJS always
85
- * passes the pointer, so on every INSERT the SQLite provider built and executed a
86
- * hidden `SELECT * FROM <table> WHERE rowid = ?` — on a statement of its own that the
87
- * connection cached as above, where no caller can reach it to release it.
88
- *
89
- * So: non-SELECTs go through `batch_execute()`, which passes `last_insert_row` as NULL;
90
- * the connection's cache entry is deleted after every execution unless the caller asks to
91
- * keep it for a statement it will run again (`ExecuteOptions.retain`, bounded by
92
- * `retained`); and the data model lets go of its prepared statement as soon as `read`
93
- * returns. Every object an execution creates is then released before this function does.
94
- *
95
- * Do NOT use `GObject.Object.run_dispose()` on the model instead: `GdaSqliteRecordset`'s
96
- * dispose clears a GWeakRef without re-initialising it, so the second dispose the
97
- * finalizer runs dereferences a cleared weak ref and the process dies with SIGSEGV.
98
- */
99
- export declare function executeStatement<T>(connection: Gda.Connection, stmt: Gda.Statement, params: Gda.Set | null, read: (model: Gda.DataModel | null, textColumns: boolean[]) => T, options?: ExecuteOptions): T;
@@ -1,36 +0,0 @@
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;
@@ -1,46 +0,0 @@
1
- import type Gda from '@girs/gda-6.0';
2
- /**
3
- * The GType a value is bound through, spelled the same way in the `##id::type`
4
- * placeholder and in the holder libgda creates from it.
5
- *
6
- * Measured against a TEXT read-back of the stored value: `gint64` round-trips every
7
- * int64 exactly — 2^53 + 1 and both extremes included — and `gdouble` yields a REAL, so
8
- * `42` reads back as `42.0`, `Infinity` as `Inf` and `NaN` as NULL. Value for value that
9
- * is what the SQL literals these replaced produced.
10
- */
11
- export type HolderType = 'gchararray' | 'gint64' | 'gdouble';
12
- /** One parameter of one execution, bound rather than written into the SQL. */
13
- export interface HolderBinding {
14
- type: HolderType;
15
- value: string | number | bigint;
16
- }
17
- /**
18
- * Let go of the strings an execution bound.
19
- *
20
- * A `Gda.Holder` keeps the value it was given until its `Gda.Set` is finalized, and the
21
- * Set is a GJS wrapper the garbage collector frees whenever it gets round to it — which
22
- * is late, because the collector cannot see the native copy. Measured on 8000 inserts of
23
- * a ~56 KB text each: 86 → 563 MiB without this, 59 → 96 MiB with it. Numbers are not
24
- * worth the call; only a string can be large.
25
- */
26
- export declare function releaseHolders(paramSet: Gda.Set | null, bindings: Map<string, HolderBinding>): void;
27
- /**
28
- * Bind the parameters of one execution to the holders libgda created for them.
29
- *
30
- * A bound parameter is what lets the SQL TEXT stay the same across executions, which is
31
- * what lets the parsed statement — and the connection's compiled `sqlite3_stmt` behind it
32
- * — be reused (see execution.ts). NULL and BLOBs are the two values that cannot take this
33
- * route and stay SQL literals: libgda refuses NULL through a holder by every spelling
34
- * (`set_value(null)`, `Gda.value_new_null()`, `force_invalid()`, and leaving it unset all
35
- * raise), and a `Uint8Array` is "Could not guess unspecified GValue type" while a
36
- * `GLib.Bytes` is a type mismatch.
37
- *
38
- * A string is the one type that MUST be bound: libgda reads `\` as an escape inside `'…'`
39
- * where SQLite does not, so a value ending in a backslash ran the quoted region past its
40
- * intended end (see parse-sql.ts).
41
- *
42
- * A missing holder is a bug in this package — the SQL and the holder set come from the
43
- * same `convertParameterSyntax` pass — so it raises rather than binding nothing and
44
- * silently writing NULL.
45
- */
46
- export declare function bindHolders(paramSet: Gda.Set | null, bindings: Map<string, HolderBinding>): void;
@@ -1,23 +0,0 @@
1
- /** One placeholder found in the SQL. `position` is -1 for named parameters. */
2
- export interface ParamInfo {
3
- gdaId: string;
4
- originalName: string;
5
- position: number;
6
- }
7
- /**
8
- * Decides what a placeholder becomes in the SQL handed to libgda.
9
- *
10
- * `StatementSync` substitutes this per execution, because the choice depends on the value:
11
- * anything libgda can carry becomes a `##id::<type>` holder so the value never enters the
12
- * SQL, and only NULL and a BLOB — which no holder accepts — become a literal, drawn from
13
- * an alphabet that cannot end a quoted region. Callers that only need to VALIDATE the SQL,
14
- * where no values exist yet, take the default.
15
- */
16
- export type PlaceholderRenderer = (param: ParamInfo) => string;
17
- export declare const asStringHolder: PlaceholderRenderer;
18
- /**
19
- * Rewrite `sql` with every parameter rendered by `render`, and report the parameters in
20
- * source order. String literals are copied verbatim so a `?` or `:name` inside one is not
21
- * mistaken for a placeholder.
22
- */
23
- export declare function convertParameterSyntax(sql: string, render?: PlaceholderRenderer): [string, ParamInfo[]];
@@ -1,26 +0,0 @@
1
- import type Gda from '@girs/gda-6.0';
2
- /**
3
- * Parse a single SQL statement and return it with its parameter set.
4
- *
5
- * **Never call `Gda.SqlParser.parse_string()` in this package.** Its `remain`
6
- * out-parameter points INTO the SQL string that was passed in — it is the unparsed tail,
7
- * not an allocation — but `Gda-6.0.gir` declares it `transfer-ownership="full"`:
8
- *
9
- * ```xml
10
- * <parameter name="remain" direction="out" transfer-ownership="full" nullable="1">
11
- * <type name="utf8" c:type="const gchar**"/>
12
- * ```
13
- *
14
- * So whenever libgda stops before the end of the string, GJS calls `g_free()` on an
15
- * interior pointer at call teardown and glibc aborts the process: `free(): invalid
16
- * pointer`, SIGABRT, no JS exception, no return value. Nothing can catch it and nothing
17
- * can be checked first — asking for the parse IS the crash. A block comment does it; so
18
- * does a statement whose string literal libgda thinks ends elsewhere than SQLite does
19
- * (libgda honours `\` as an escape inside `'…'`, SQLite does not — which is how a mail
20
- * body ending in a backslash killed a consumer mid-import).
21
- *
22
- * `gda_connection_parse_sql_string()` takes no `remain` at all, so the same input raises
23
- * an ordinary catchable error. It also hands back the `Gda.Set` of parameter holders,
24
- * which is what lets values be BOUND instead of spliced into the SQL text.
25
- */
26
- export declare function parseSql(connection: Gda.Connection, sql: string): [Gda.Statement, Gda.Set | null];
@@ -1,25 +0,0 @@
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,39 +0,0 @@
1
- /**
2
- * What a statement does.
3
- *
4
- * `other` is everything this package does not read rows from and does not treat as a
5
- * write: a PRAGMA, a CREATE, an EXPLAIN. Those keep the path they had before — see
6
- * `returnsRows()` in execution.ts.
7
- */
8
- export type StatementKind = 'rows' | 'write' | 'other';
9
- /**
10
- * Does this statement return rows, write, or neither?
11
- *
12
- * The answer comes from the SQL TEXT, because libgda's own classification cannot be
13
- * asked: a statement with a CTE is UNKNOWN to it whatever it does (see the header).
14
- *
15
- * A statement that does not start with `WITH` is classified by its first word. A
16
- * `WITH` statement is classified by the verb that follows its CTE definitions — the
17
- * CTEs themselves may hide anything, so the verb is what decides, and `WITH q AS
18
- * (SELECT 1) INSERT INTO t SELECT * FROM q` is a WRITE.
19
- */
20
- export declare function statementKind(sql: string): StatementKind;
21
- /**
22
- * The text the provider must be given for a statement of this kind.
23
- *
24
- * The provider dispatches on the FIRST WORD of the text it renders (see the header), so
25
- * a statement that returns rows but does not start with `SELECT` has to be stated in a
26
- * shape that does: `SELECT * FROM ( … )` — a derived table, which SQLite accepts around
27
- * a whole CTE statement. The rows and their column names are the inner statement's:
28
- * SQLite names the columns of a subquery after the ones its own SELECT produced.
29
- *
30
- * A statement that already starts with `SELECT` is handed over unchanged, and so is
31
- * every statement that does not return rows: a write must stay a write, and the
32
- * provider runs it as a command — which is what an INSERT, an UPDATE and a DELETE
33
- * need.
34
- *
35
- * A trailing `;` moves OUT of the parentheses: it would end the statement there and
36
- * leave the parenthesis unclosed ("incomplete input"). SQLite does not need it, and
37
- * libgda's parser drops a trailing `;` of its own accord.
38
- */
39
- export declare function providerSql(sql: string, kind: StatementKind): string;