@itwin/core-backend
Version:
iTwin.js backend components
375 lines • 17.2 kB
TypeScript
/** @packageDocumentation
* @module SQLite
*/
import { BentleyError, DbResult, GuidString, Id64String } from "@itwin/core-bentley";
import { IModelJsNative } from "@bentley/imodeljs-native";
/** Marks a string as either an [Id64String]($core-bentley) or [GuidString]($core-bentley), so
* that it can be passed to the [bindValue]($backend.SqliteStatement) or [bindValues]($backend.SqliteStatement)
* methods of [SqliteStatement]($backend).
* @internal
*/
export interface StringParam {
id?: Id64String;
guid?: GuidString;
}
/** parameter Index (1-based), or name of the parameter (including the initial ':', '@' or '$')
* @public
*/
export type BindParameter = number | string;
/** Executes SQLite SQL statements.
*
* A statement must be prepared before it can be executed, and it must be released when no longer needed.
* See [IModelDb.withPreparedSqliteStatement]($backend) or
* [ECDb.withPreparedSqliteStatement]($backend) for a convenient and
* reliable way to prepare, execute, and then release a statement.
*
* A statement may contain parameters that must be filled in before use by calling [SqliteStatement.bindValue]($backend)
* or [SqliteStatement.bindValues]($backend).
*
* Once prepared (and parameters are bound, if any), the statement is executed by calling [SqliteStatement.step]($backend).
* In case of an **SQL SELECT** statement, the current row can be retrieved with [SqliteStatement.getRow]($backend) as
* a whole, or with [SqliteStatement.getValue]($backend) when individual values are needed.
* Alternatively, query results of an **SQL SELECT** statement can be stepped through by using
* standard iteration syntax, such as `for of`.
*
* > Preparing a statement can be time-consuming. The best way to reduce the effect of this overhead is to cache and reuse prepared
* > statements. A cached prepared statement may be used in different places in an app, as long as the statement is general enough.
* > The key to making this strategy work is to phrase a statement in a general way and use placeholders to represent parameters that will vary on each use.
* @public
*/
export declare class SqliteStatement implements IterableIterator<any>, Disposable {
private _sql;
private _stmt;
private _db;
constructor(_sql: string);
get stmt(): IModelJsNative.SqliteStatement;
get sql(): string;
/** Check if this statement has been prepared successfully or not */
get isPrepared(): boolean;
/** Prepare this statement prior to first use.
* @param db The DgnDb or ECDb to prepare the statement against
* @param sql The SQL statement string to prepare
* @param logErrors Determine if errors are logged or not
* @throws if the SQL statement cannot be prepared. Normally, prepare fails due to SQL syntax errors or references to tables or properties that do not exist.
* The error.message property will provide details.
*/
prepare(db: IModelJsNative.AnyDb, logErrors?: boolean): void;
/** Indicates whether the prepared statement makes no **direct* changes to the content of the file
* or not. See [SQLite docs](https://www.sqlite.org/c3ref/stmt_readonly.html) for details.
*/
get isReadonly(): boolean;
/** Reset this statement so that the next call to step will return the first row, if any.
*/
reset(): void;
/** Call this function when finished with this statement. This releases the native resources held by the statement. */
[Symbol.dispose](): void;
/** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
dispose(): void;
/**
* Call `step` on this statement and determine whether a new row is available.
* Use this method only when this statement has been prepared with a SELECT statement.
* @return true if a new row is available, false otherwise.
* @throws if `step` returns anything other than BE_SQLITE_ROW or BE_SQLITE_DONE.
*/
nextRow(): boolean;
throwSqlError(rc: DbResult): void;
stepForWrite(): void;
/** Binds a value to the specified SQL parameter.
* The value must be of one of these types:
* JavaScript Type | SQLite Type
* --- | ---
* undefined | NULL
* boolean | INTEGER with true being bound as 1 and false as 0
* number | INTEGER if number is integral or REAL if number is not integral
* string | TEXT
* Uint8Array or ArrayBuffer | BLOB
* [StringParam]($backend) where member **id** is set | INTEGER
* [StringParam]($backend) where member **guid** is set | BLOB
*
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param value Value to bind.
* @throws [IModelError]($common) if the value is of an unsupported type or in
* case of other binding errors.
*/
bindValue(parameter: BindParameter, value: any): void;
/** Bind an integer parameter
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val integer to bind.
*/
bindInteger(parameter: BindParameter, val: number): void;
/** Bind an integer parameter if it is defined. Otherwise do nothing.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val integer to bind.
*/
maybeBindInteger(parameter: BindParameter, val?: number): void;
/** Bind a boolean parameter.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val boolean to bind.
*/
bindBoolean(parameter: BindParameter, val: boolean): void;
/** Bind a boolean parameter if it is defined. Otherwise do nothing.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val boolean to bind.
*/
maybeBindBoolean(parameter: BindParameter, val?: boolean): void;
/** JSON.stringify a property value and bind the JSON string.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val object to bind.
* @internal
*/
bindProps<T>(colIndex: number, val: T): void;
/** JSON.stringify a property value if it is defined, and bind the JSON string. Otherwise do nothing.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val object to bind.
* @internal
*/
maybeBindProps<T>(colIndex: number, val?: T): void;
/** Bind a double parameter
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val double to bind.
*/
bindDouble(parameter: BindParameter, val: number): void;
/** Bind a double parameter if it is defined. Otherwise do nothing.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val double to bind.
*/
maybeBindDouble(parameter: BindParameter, val?: number): void;
/** Bind a string parameter
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val string to bind.
*/
bindString(parameter: BindParameter, val: string): void;
/** Bind a string parameter if it is defined. Otherwise do nothing.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val string to bind.
*/
maybeBindString(parameter: BindParameter, val?: string): void;
/** Bind an Id64String parameter as a 64-bit integer
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val Id to bind.
*/
bindId(parameter: BindParameter, id: Id64String): void;
/** Bind a Guid parameter
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val Guid to bind.
*/
bindGuid(parameter: BindParameter, guid: GuidString): void;
/** Bind a blob parameter
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val blob to bind.
*/
bindBlob(parameter: BindParameter, blob: Uint8Array): void;
/** Bind a blob parameter if it is defined. Otherwise do nothing.
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
* @param val blob to bind.
*/
maybeBindBlob(parameter: BindParameter, val?: Uint8Array): void;
/** Bind null to a parameter
* @param parameter Index (1-based) or name of the parameter (including the initial ':', '@' or '$')
*/
bindNull(parameter: BindParameter): void;
/** Bind values to all parameters in the statement.
* @param values The values to bind to the parameters.
* Pass an *array* of values if the parameters are *positional*.
* Pass an *object of the values keyed on the parameter name* for *named parameters*.
* The values in either the array or object must match the respective types of the parameter.
* See [[SqliteStatement.bindValue]] for details on the supported types.
*/
bindValues(values: any[] | object): void;
/** Clear any bindings that were previously set on this statement.
* @throws [IModelError]($common) in case of errors
*/
clearBindings(): void;
/** Step this statement to the next row.
*
* For **SQL SELECT** statements the method returns
* - [DbResult.BE_SQLITE_ROW]($core-bentley) if the statement now points successfully to the next row.
* - [DbResult.BE_SQLITE_DONE]($core-bentley) if the statement has no more rows.
* - Error status in case of errors.
*
* For **SQL INSERT, UPDATE, DELETE** statements the method returns
* - [DbResult.BE_SQLITE_DONE]($core-bentley) if the statement has been executed successfully.
* - Error status in case of errors.
*/
step(): DbResult;
/** Get the query result's column count (only for SQL SELECT statements). */
getColumnCount(): number;
/** Get the value for the column at the given index in the query result.
* @param columnIx Index of SQL column in query result (0-based)
*/
getValue(columnIx: number): SqliteValue;
/** Determine whether the value of the specified column is null
* @param colIndex Index of SQL column in query result (0-based)
*/
isValueNull(colIndex: number): boolean;
/** Get a size in bytes of a blob or text column
* @param colIndex Index of SQL column in query result (0-based)
*/
getColumnBytes(colIndex: number): number;
/** Get a value as a blob
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueBlob(colIndex: number): Uint8Array;
/** Get the value as a blob, or undefined if it is null.
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueBlobMaybe(colIndex: number): Uint8Array | undefined;
/** Get a value as a double
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueDouble(colIndex: number): number;
/** Get the value as an double, or undefined if it is null.
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueDoubleMaybe(colIndex: number): number | undefined;
/** Get a value as a integer
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueInteger(colIndex: number): number;
/** Get the value as an integer, or undefined if it is null.
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueIntegerMaybe(colIndex: number): number | undefined;
/** Get a value as a string
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueString(colIndex: number): string;
/** Get the value as a string, or undefined if it is null.
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueStringMaybe(colIndex: number): string | undefined;
/** Get a value as an Id
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueId(colIndex: number): Id64String;
/** Get a value as a Guid
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueGuid(colIndex: number): GuidString;
/** Get the value as a boolean. Returns `false` if the column is null.
* @param colIndex Index of SQL column in query result (0-based)
*/
getValueBoolean(colIndex: number): boolean;
/** Get the value of a [julianday](https://www.sqlite.org/lang_datefunc.html) column as a JavaScript `Date`.
* @param colIndex Index of SQL column in query result (0-based)
* @beta
*/
getValueDate(colIndex: number): Date;
/** Get the value as a "props" JSON string, then parse it and return the object
* @param colIndex Index of SQL column in query result (0-based)
* @internal
*/
getProps<T>(colIndex: number): T;
/** Get the value as a "props" JSON string, then parse it and return the object.
* If the column is null, return undefined.
* @param colIndex Index of SQL column in query result (0-based)
* @internal
*/
getPropsMaybe<T>(colIndex: number): T | undefined;
/** Get the current row.
* The returned row is formatted as JavaScript object where every SELECT clause item becomes a property in the JavaScript object.
*
* The SQL select clause item's name becomes the member name of the JavaScript object, **with the first character lowered**.
*
* SQLite Type | JavaScript Type
* --- | ---
* [SqliteValueType.Null]($backend) | undefined
* [SqliteValueType.Integer]($backend) | number
* [SqliteValueType.Double]($backend) | number
* [SqliteValueType.String]($backend) | string
* [SqliteValueType.Blob]($backend) | Uint8Array
*/
getRow(): any;
private static determineResultRowPropertyName;
/** Calls step when called as an iterator.
*/
next(): IteratorResult<any>;
/** The iterator that will step through the results of this statement. */
[Symbol.iterator](): IterableIterator<any>;
}
/** Data type of a value in in an SQLite SQL query result.
* See also:
* - [SqliteValue]($backend)
* - [SqliteStatement]($backend)
* - [SqliteStatement.getValue]($backend)
* @public
*/
export declare enum SqliteValueType {
Integer = 1,
Double = 2,
String = 3,
Blob = 4,
Null = 5
}
/** Value of a column in a row of an SQLite SQL query result.
* See also:
* - [SqliteStatement]($backend)
* - [SqliteStatement.getValue]($backend)
* @public
*/
export declare class SqliteValue {
private readonly _stmt;
private readonly _colIndex;
constructor(stmt: IModelJsNative.SqliteStatement, colIndex: number);
/** Indicates whether the value is NULL or not. */
get isNull(): boolean;
/** Gets the data type of the value. */
get type(): SqliteValueType;
/** Gets the name of the column of the value. */
get columnName(): string;
/** Gets the SqlValue as JavaScript value.
*
* SQLite Type | JavaScript Type
* --- | ---
* [SqliteValueType.Null]($backend) | undefined
* [SqliteValueType.Integer]($backend) | number
* [SqliteValueType.Double]($backend) | number
* [SqliteValueType.String]($backend) | string
* [SqliteValueType.Blob]($backend) | Uint8Array
*/
get value(): any;
/** Get the value as Blob */
getBlob(): Uint8Array;
/** Get the value as a double value */
getDouble(): number;
/** Get the value as a integer value */
getInteger(): number;
/** Get the value as a string value */
getString(): string;
/** Get the value as an Id value */
getId(): Id64String;
/** Get the value as a Guid value */
getGuid(): GuidString;
}
interface Statement {
isPrepared: boolean;
sql: string;
dispose(): void;
reset(): void;
clearBindings(): void;
}
/** A cache for previously prepared SqliteStatements.
* It only holds Statements after they are no longer in use, resetting and clearing their bindings before saving them.
* When a request to use a statement from the cache is made, it is first removed from the cache.
* @internal
*/
export declare class StatementCache<Stmt extends Statement> {
private _cache;
constructor(maxCount?: number);
get size(): number;
addOrDispose(stmt: Stmt): void;
findAndRemove(sql: string): Stmt | undefined;
clear(): void;
}
/** @public */
export declare namespace SqliteStatement {
class DbError extends BentleyError {
/** A string that indicates the type of problem that caused the exception. */
readonly errorId: ErrorId;
/** @internal */
constructor(errorId: ErrorId, errNum: number, message: string);
}
type ErrorId = "DuplicateValue" | "SqlLogicError" | "ValueIsInUse";
}
export {};
//# sourceMappingURL=SqliteStatement.d.ts.map