Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate UseJsPropertyNames and ECSqlStatement (which defaults to UseJsPropertyNames) #7315

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions core/backend/src/ChangeSummaryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as path from "path";
import { BackendLoggerCategory } from "./BackendLoggerCategory";
import { BriefcaseManager } from "./BriefcaseManager";
import { ECDb, ECDbOpenMode } from "./ECDb";
import { ECSqlStatement } from "./ECSqlStatement";
import { ECSqlInsertResult, ECSqlStatement, ECSqlWriteStatement } from "./ECSqlStatement";
import { BriefcaseDb, IModelDb, TokenArg } from "./IModelDb";
import { IModelHost, KnownLocations } from "./IModelHost";
import { IModelJsFs } from "./IModelJsFs";
Expand Down Expand Up @@ -195,8 +195,8 @@ export class ChangeSummaryManager {
}

private static addExtendedInfos(changesFile: ECDb, changeSummaryId: Id64String, changesetWsgId: GuidString, changesetParentWsgId?: GuidString, description?: string, changesetPushDate?: string, changeSetUserCreated?: GuidString): void {
changesFile.withPreparedStatement("INSERT INTO imodelchange.ChangeSet(Summary.Id,WsgId,ParentWsgId,Description,PushDate,UserCreated) VALUES(?,?,?,?,?,?)",
(stmt: ECSqlStatement) => {
changesFile.withCachedWriteStatement("INSERT INTO imodelchange.ChangeSet(Summary.Id,WsgId,ParentWsgId,Description,PushDate,UserCreated) VALUES(?,?,?,?,?,?)",
(stmt: ECSqlWriteStatement) => {
stmt.bindId(1, changeSummaryId);
stmt.bindString(2, changesetWsgId);
if (changesetParentWsgId)
Expand All @@ -211,9 +211,9 @@ export class ChangeSummaryManager {
if (changeSetUserCreated)
stmt.bindString(6, changeSetUserCreated);

const r: DbResult = stmt.step();
if (r !== DbResult.BE_SQLITE_DONE)
throw new IModelError(r, `Failed to add changeset information to extracted change summary ${changeSummaryId}`);
const r: ECSqlInsertResult = stmt.stepForInsert();
if (r.status !== DbResult.BE_SQLITE_DONE)
throw new IModelError(r.status, `Failed to add changeset information to extracted change summary ${changeSummaryId}`);
});
}

Expand Down
82 changes: 81 additions & 1 deletion core/backend/src/ECDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { IModelJsNative } from "@bentley/imodeljs-native";
import { DbQueryRequest, ECSchemaProps, ECSqlReader, IModelError, QueryBinder, QueryOptions, QueryOptionsBuilder } from "@itwin/core-common";
import { BackendLoggerCategory } from "./BackendLoggerCategory";
import { ConcurrentQuery } from "./ConcurrentQuery";
import { ECSqlStatement } from "./ECSqlStatement";
import { ECSqlStatement, ECSqlWriteStatement } from "./ECSqlStatement";
import { IModelNative } from "./internal/NativePlatform";
import { SqliteStatement, StatementCache } from "./SqliteStatement";
import { _nativeDb } from "./internal/Symbols";
Expand All @@ -32,6 +32,7 @@ export enum ECDbOpenMode {
*/
export class ECDb implements IDisposable {
private _nativeDb?: IModelJsNative.ECDb;
// eslint-disable-next-line @typescript-eslint/no-deprecated
private readonly _statementCache = new StatementCache<ECSqlStatement>();
private _sqliteStatementCache = new StatementCache<SqliteStatement>();

Expand Down Expand Up @@ -146,6 +147,76 @@ export class ECDb implements IDisposable {
return this[_nativeDb].getSchemaProps(name);
}

/**
* Use a prepared ECSQL statement, potentially from the statement cache. If the requested statement doesn't exist
* in the statement cache, a new statement is prepared. After the callback completes, the statement is reset and saved
* in the statement cache so it can be reused in the future. Use this method for ECSQL statements that will be
* reused often and are expensive to prepare. The statement cache holds the most recently used statements, discarding
* the oldest statements as it fills. For statements you don't intend to reuse, instead use [[withStatement]].
* @param sql The SQLite SQL statement to execute
* @param callback the callback to invoke on the prepared statement
* @param logErrors Determines if error will be logged if statement fail to prepare
* @returns the value returned by `callback`.
* @see [[withWriteStatement]]
* @beta
*/
public withCachedWriteStatement<T>(ecsql: string, callback: (stmt: ECSqlWriteStatement) => T, logErrors = true): T {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const stmt = this._statementCache.findAndRemove(ecsql) ?? this.prepareStatement(ecsql, logErrors);
const release = () => this._statementCache.addOrDispose(stmt);
try {
const val = callback(new ECSqlWriteStatement(stmt));
if (val instanceof Promise) {
val.then(release, release);
} else {
release();
}
return val;
} catch (err) {
release();
throw err;
}
}

/**
* Prepared and execute a callback on an ECSQL statement. After the callback completes the statement is disposed.
* Use this method for ECSQL statements are either not expected to be reused, or are not expensive to prepare.
* For statements that will be reused often, instead use [[withPreparedStatement]].
* @param sql The SQLite SQL statement to execute
* @param callback the callback to invoke on the prepared statement
* @param logErrors Determines if error will be logged if statement fail to prepare
* @returns the value returned by `callback`.
* @see [[withCachedWriteStatement]]
* @beta
*/
public withWriteStatement<T>(ecsql: string, callback: (stmt: ECSqlWriteStatement) => T, logErrors = true): T {
const stmt = this.prepareWriteStatement(ecsql, logErrors);
const release = () => stmt.dispose();
try {
const val = callback(stmt);
if (val instanceof Promise) {
val.then(release, release);
} else {
release();
}
return val;
} catch (err) {
release();
throw err;
}
}

/** Prepare an ECSQL statement.
* @param ecsql The ECSQL statement to prepare
* @param logErrors Determines if error will be logged if statement fail to prepare
* @throws [IModelError]($common) if there is a problem preparing the statement.
* @beta
*/
public prepareWriteStatement(ecsql: string, logErrors = true): ECSqlWriteStatement {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return new ECSqlWriteStatement(this.prepareStatement(ecsql, logErrors));
}

/**
* Use a prepared ECSQL statement, potentially from the statement cache. If the requested statement doesn't exist
* in the statement cache, a new statement is prepared. After the callback completes, the statement is reset and saved
Expand All @@ -158,8 +229,11 @@ export class ECDb implements IDisposable {
* @returns the value returned by `callback`.
* @see [[withStatement]]
* @public
* @deprecated in 4.10. Use [[createQueryReader]] for SELECT statements and [[withCachedWriteStatement]] for INSERT/UPDATE/DELETE instead.
*/
// eslint-disable-next-line @typescript-eslint/no-deprecated
public withPreparedStatement<T>(ecsql: string, callback: (stmt: ECSqlStatement) => T, logErrors = true): T {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const stmt = this._statementCache.findAndRemove(ecsql) ?? this.prepareStatement(ecsql, logErrors);
const release = () => this._statementCache.addOrDispose(stmt);
try {
Expand All @@ -186,8 +260,11 @@ export class ECDb implements IDisposable {
* @returns the value returned by `callback`.
* @see [[withPreparedStatement]]
* @public
* @deprecated in 4.10. Use [[createQueryReader]] for SELECT statements and [[withWriteStatement]] for INSERT/UPDATE/DELETE instead.
*/
// eslint-disable-next-line @typescript-eslint/no-deprecated
public withStatement<T>(ecsql: string, callback: (stmt: ECSqlStatement) => T, logErrors = true): T {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const stmt = this.prepareStatement(ecsql, logErrors);
const release = () => stmt.dispose();
try {
Expand All @@ -208,8 +285,11 @@ export class ECDb implements IDisposable {
* @param ecsql The ECSQL statement to prepare
* @param logErrors Determines if error will be logged if statement fail to prepare
* @throws [IModelError]($common) if there is a problem preparing the statement.
* @deprecated in 4.10. Use [[prepareWriteStatement]] when preparing an INSERT/UPDATE/DELETE statement or [[createQueryReader]] to execute a SELECT statement.
*/
// eslint-disable-next-line @typescript-eslint/no-deprecated
public prepareStatement(ecsql: string, logErrors = true): ECSqlStatement {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const stmt = new ECSqlStatement();
stmt.prepare(this[_nativeDb], ecsql, logErrors);
return stmt;
Expand Down
Loading
Loading