diff --git a/sqflite/ohos/oh-package-lock.json5 b/sqflite/ohos/oh-package-lock.json5 index 36f40b070c5dec9f7dbedae63c685dc3d49071e3..aab91144ec9e02af64e4c049cb314ed2c3adbb37 100644 --- a/sqflite/ohos/oh-package-lock.json5 +++ b/sqflite/ohos/oh-package-lock.json5 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Database.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Database.ets new file mode 100644 index 0000000000000000000000000000000000000000..fab17a75ffe8fab2045578b0e036516aafaaa5d8 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/Database.ets @@ -0,0 +1,350 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import common from '@ohos.app.ability.common'; +import relationalStore from '@ohos.data.relationalStore'; +import { Operation } from './operation/Operation'; +import { SqlCommand } from './SqlCommand'; +import { ValueType } from '@ohos.data.ValuesBucket'; +import { Constant } from './Constant'; +import { BusinessError } from '@ohos.base'; +import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; +import { MethodCallOperation } from './operation/MethodCallOperation'; +import { BatchOperation } from './operation/BatchOperation'; + +export class Database { + public context: common.Context; + public path: string; + public id: number; + public singleInstance: boolean; + public logLevel: number; + private static lastTransactionId: number = 0; + private static currentTransactionId: number | null; + private static transactionDepth: number = 0; + constructor(context: common.Context, path: string, id: number, singleInstance: boolean, logLevel: number) { + this.context = context; + this.path = path; + this.id = id; + this.singleInstance = singleInstance; + this.logLevel = logLevel; + } + + private static enterOrLeaveInTransaction(value: Boolean): void { + if(value == true) { + Database.transactionDepth++; + } else if (value == false) { + Database.transactionDepth--; + } + } + + private static handleException(operation: Operation, err: BusinessError) { + let code = err.code; + let message = err.message; + operation.error(Constant.SQLITE_ERROR, message + '' + code, ''); + } + + private static async executeOrError(operation: Operation, db: relationalStore.RdbStore): Promise { + let command: SqlCommand = operation.getSqlCommand(); + let operationInTransaction: Boolean = operation.getInTransactionChange(); + let sqlArguments: ValueType[] | undefined = operation.getArgument(Constant.PARAM_SQL_ARGUMENTS); + let sql: string = command.getSql(); + try{ + if(sqlArguments == undefined || sqlArguments.length < 1) { + let promise = await db.executeSql(sql); + } else { + let promise = await db.executeSql(sql, sqlArguments); + } + + Database.enterOrLeaveInTransaction(operationInTransaction); + return true; + } catch(err) { + Database.handleException(operation, err); + return false; + } + } + + /// execute + public static async execute(operation: Operation, db: relationalStore.RdbStore): Promise { + let command: SqlCommand = operation.getSqlCommand(); + let sql: string = command.getSql(); + if(sql == 'BEGIN IMMEDIATE') { + db.beginTransaction(); + operation.success(null); + return; + } else if(sql == 'COMMIT') { + db.commit(); + operation.success(null); + return; + } else if (sql == 'BEGIN EXCLUSIVE') { + operation.success(null); + return; + } + + let inTransactionChange: Boolean = operation.getInTransactionChange(); + let enteringTransaction: boolean = (inTransactionChange == true && operation.hasNullTransactionId()); + if(enteringTransaction) { + Database.currentTransactionId = ++ (Database.lastTransactionId); + } + + let executeSuccess: boolean = await Database.executeOrError(operation, db); + if(!executeSuccess) { + // Revert if needed + if(enteringTransaction) { + Database.currentTransactionId = null; + } + } else if(enteringTransaction) { + /// Return the transaction id; + if(Database.currentTransactionId != null) { + let res: Map = new Map(); + res.set(Constant.PARAM_TRANSACTION_ID, Database.currentTransactionId); + operation.success(res); + } else { + operation.success(null); + } + } else { + if(inTransactionChange == false) { + Database.currentTransactionId = null; + } + operation.success(null); + } + } + + public static async doExecute(operation: Operation, db: relationalStore.RdbStore): Promise { + let executeSuccess: boolean = await Database.executeOrError(operation, db); + if(!executeSuccess) { + return false; + } + operation.success(null); + return true; + } + + /// insert + public static insert(operation: Operation, db: relationalStore.RdbStore): void { + Database.doInsert(operation, db); + } + + private static async doInsert(operation: Operation, db: relationalStore.RdbStore): Promise { + let executeSuccess: boolean = await Database.executeOrError(operation, db); + if(!executeSuccess) { + return false; + } + + // don't get last id if not expected + if(operation.getNoResult()) { + operation.success(null); + return true; + } + operation.success(1); + return true; + } + + /// update + public static update(operation: Operation, db: relationalStore.RdbStore): void { + Database.doUpdate(operation, db); + } + + private static async doUpdate(operation: Operation, db: relationalStore.RdbStore): Promise { + let executeSuccess: boolean = await Database.executeOrError(operation, db); + if(!executeSuccess) { + return false; + } + + // don't get last id if not expected + if(operation.getNoResult()) { + operation.success(null); + return true; + } + operation.success(1); + return true; + } + + /// query + public static query(operation: Operation, db: relationalStore.RdbStore): void { + Database.doQuery(operation, db); + } + + private static async doQuery(operation: Operation, db: relationalStore.RdbStore): Promise { + + let command: SqlCommand = operation.getSqlCommand(); + let sql: string = command.getSql(); + + if(sql == 'PRAGMA user_version') { + let versionMap: Map = new Map(); + versionMap.set(Constant.PARAM_COLUMNS, ['user_version']); + versionMap.set(Constant.PARAM_ROWS, [[db.version]]); + operation.success(versionMap); + return true; + } + + let cursorPageSize: number | undefined = operation.getArgument(Constant.PARAM_CURSOR_PAGE_SIZE); + let sqlArguments: ValueType[] | undefined = operation.getArgument(Constant.PARAM_SQL_ARGUMENTS); + let suc: boolean = false; + + if(sqlArguments != undefined && sqlArguments.length > 0) { + try{ + let resultSet = await db.querySql(sql, sqlArguments); + suc = Database.handleQuerySqlResult(operation, resultSet, cursorPageSize); + return suc; + } catch(err) { + Database.handleException(operation, err); + return false; + } + } else { + try{ + let resultSet = await db.querySql(sql); + suc = Database.handleQuerySqlResult(operation, resultSet, cursorPageSize); + return suc; + } catch(err) { + Database.handleException(operation, err); + return false; + } + } + } + + private static handleQuerySqlResult(operation: Operation, resultSet: relationalStore.ResultSet, cursorPageSize: number | undefined): boolean { + + let results: Map = new Map(); + let rows: Array> = new Array>(); + let columns: Array | null = null; + let columnCount: number = 0; + + // resultSet是一个数据集合得游标,默认值想第-1个记录,有效的数据从0开始 + while(resultSet.goToNextRow()) { + if(columns == null) { + columnCount = resultSet.columnCount; + columns = new Array(); + rows = new Array>(); + for(let i = 0; i < columnCount; i++) { + columns.push(resultSet.getColumnName(i)); + } + results.set(Constant.PARAM_COLUMNS, columns); + results.set(Constant.PARAM_ROWS, rows); + } + + let row = Database.cursorRowToList(resultSet, columnCount); + rows.push(row); + if(cursorPageSize != null) { + if(rows.length >= cursorPageSize) { + break; + } + } + } + + operation.success(results); + // 释放数据集的内存 + resultSet.close(); + return true; + } + + static cursorRowToList(cursor: relationalStore.ResultSet, length: number): Array { + let list = new Array(); + + for(let i = 0; i < length; i++) { + let value: Object = Database.cursorValue(cursor, i); + // let value: Object = 'cursorValue(cursor, i);' + // if(Debug.EXTRA_LOGV) { + // String type = null; + // if(value != null) { + // if(value.getClass().isArray()) { + // type = "array(" + value.getClass().GetComponentType().getName() + ")"; + // } else { + // type = value.getClass().getName(); + // } + // } + // Log.d(TAG, "column " + i + "" + cursor.getType(i) + ": " + value + (type == null ? "" : "(" + type + ")")); + // } + list.push(value); + } + return list; + } + + static cursorValue(cursor: relationalStore.ResultSet, index: number): string { + return cursor.getString(index); + } + + /// batch + public static async batch(call: MethodCall, result: MethodResult, db: relationalStore.RdbStore): Promise { + + let mainOperation: MethodCallOperation = new MethodCallOperation(call, result); + let noResult: boolean = mainOperation.getNoResult(); + let continueOnError: boolean = mainOperation.getContinueOnError(); + + let operations: Array> = mainOperation.getArgument(Constant.PARAM_OPERATIONS) as Array>; + let results: Array> = new Array(); + + for(let index = 0; index < operations.length; index++) { + + const map: Map = operations[index]; + let operation: BatchOperation = new BatchOperation(map, noResult); + const method: string = operation.getMethod(); + + let executeSuc: boolean; + switch(method) { + case Constant.METHOD_EXECUTE: + executeSuc = await Database.doExecute(operation, db); + if(executeSuc) { + operation.handleSuccess(results); + } else if(continueOnError) { + operation.handleErrorContinue(results); + } else { + return; + } + break; + case Constant.METHOD_INSERT: + executeSuc = await Database.doInsert(operation, db); + if(executeSuc) { + operation.handleSuccess(results); + } else if(continueOnError) { + operation.handleErrorContinue(results); + } else { + operation.handleError(result); + return; + } + break; + case Constant.METHOD_QUERY: + executeSuc = await Database.doQuery(operation, db); + if(executeSuc) { + operation.handleSuccess(results); + } else if(continueOnError) { + operation.handleErrorContinue(results); + } else { + operation.handleError(result); + return; + } + break; + case Constant.METHOD_UPDATE: + executeSuc = await Database.doUpdate(operation, db); + if(executeSuc) { + operation.handleSuccess(results); + } else if(continueOnError) { + operation.handleErrorContinue(results); + } else { + operation.handleError(result); + return; + } + break; + default: + result.error(Constant.ERROR_BAD_PARAM, "Batch method " + method + "not supported", null); + return; + } + } + if(noResult) { + result.success(null); + } else { + result.success(results); + } + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets index 4484b221b363141e80b19185da8ceb42db6138ed..5f786da9604badc582ef8547c13ba1d1befa6b24 100644 --- a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqflitePlugin.ets @@ -35,6 +35,8 @@ import { ValueType } from '@ohos.data.ValuesBucket'; import { SqlHelper } from './sql_helper'; import { Constant } from './constant'; import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; +import { Database } from './Database'; +import { MethodCallOperation } from './operation/MethodCallOperation'; const TAG: string = "SqflitePlugin"; @@ -162,8 +164,8 @@ export default class SqflitePlugin extends SqfliteApi implements FlutterPlugin, ///检查数据库是否存在 async handleDatabaseExistsCall(call: MethodCall, result: MethodResult): Promise { - let daPath: string = call.argument(Constant.PARAM_PATH); - let isExist: boolean = await SqfLiteHelper.checkDatabaseExisted(daPath); + let dbPath: string = call.argument(Constant.PARAM_PATH); + let isExist: boolean = await SqfLiteHelper.checkDatabaseExisted(dbPath); result.success(isExist); } @@ -173,10 +175,9 @@ export default class SqflitePlugin extends SqfliteApi implements FlutterPlugin, if (rdbStore == null) { return; } + let operation: MethodCallOperation = new MethodCallOperation(call, result); - let sql: string = call.argument(Constant.PARAM_SQL); - let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); - SqfLiteHelper.execute(sql, sqlArguments, call, result, rdbStore); + Database.execute(operation, rdbStore); } ///插入数据 @@ -185,21 +186,43 @@ export default class SqflitePlugin extends SqfliteApi implements FlutterPlugin, if (rdbStore == null) { return; } + let sql: string = call.argument(Constant.PARAM_SQL); - let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); - await SqfLiteHelper.insertSql(sql, sqlArguments, call, result, rdbStore); + let dataBaseId: number = call.argument(Constant.PARAM_ID); + let databaseName: string = SqfLiteHelper.dBIdList.get(dataBaseId) as string; + let tableName: string = SqlHelper.getInsertSqlTableName(sql); + + let tableExisted = await SqfLiteHelper.checkTable(databaseName, tableName); + if(tableName.length > 0 && !tableExisted) { + result.error(Constant.SQLITE_ERROR, 'no such table:' + tableName, ''); + return; + } + + let operation: MethodCallOperation = new MethodCallOperation(call, result); + Database.insert(operation, rdbStore); } ///查询数据 async handleQueryCall(call: MethodCall, result: MethodResult): Promise { + Log.i(TAG, "begin query data"); let rdbStore = SqfLiteHelper.getDatabaseOrError(call, result); if (rdbStore == null) { return; } + let sql: string = call.argument(Constant.PARAM_SQL); - let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); - let cursorPageSize: number | undefined = call.argument(Constant.PARAM_CURSOR_PAGE_SIZE); - await SqfLiteHelper.querySql(sql, sqlArguments, call, result, rdbStore, cursorPageSize); + let dataBaseId: number = call.argument(Constant.PARAM_ID); + let databaseName: string = SqfLiteHelper.dBIdList.get(dataBaseId) as string; + let tableName: string = SqlHelper.getQuerySqlTableName(sql); + + let tableExisted = await SqfLiteHelper.checkTable(databaseName, tableName); + if(tableName.length > 0 && !tableExisted) { + result.error(Constant.SQLITE_ERROR, 'no such table:' + tableName, ''); + return; + } + + let operation: MethodCallOperation = new MethodCallOperation(call, result); + Database.query(operation, rdbStore); } ///更新(包括删除)数据 @@ -208,9 +231,20 @@ export default class SqflitePlugin extends SqfliteApi implements FlutterPlugin, if (rdbStore == null) { return; } + let sql: string = call.argument(Constant.PARAM_SQL); - let sqlArguments: ValueType[] | undefined = call.argument(Constant.PARAM_SQL_ARGUMENTS); - await SqfLiteHelper.updateSql(sql, sqlArguments, call, result, rdbStore); + let dataBaseId: number = call.argument(Constant.PARAM_ID); + let databaseName: string = SqfLiteHelper.dBIdList.get(dataBaseId) as string; + let tableName: string = SqlHelper.getUpdateSqlTableName(sql); + + let tableExisted = await SqfLiteHelper.checkTable(databaseName, tableName); + if(tableName.length > 0 && !tableExisted) { + result.error(Constant.SQLITE_ERROR, 'no such table:' + tableName, ''); + return; + } + + let operation: MethodCallOperation = new MethodCallOperation(call, result); + Database.update(operation, rdbStore); } ///batch操作 @@ -219,7 +253,7 @@ export default class SqflitePlugin extends SqfliteApi implements FlutterPlugin, if (rdbStore == null) { return; } - SqfLiteHelper.batch(call, result, rdbStore); + Database.batch(call, result, rdbStore); } ///Options操作,设置LogLevel,仅限开发,已废弃 diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqlCommand.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqlCommand.ets new file mode 100644 index 0000000000000000000000000000000000000000..675eaed792111cbadeee635140fb03d05bbb6271 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/SqlCommand.ets @@ -0,0 +1,76 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import ArrayList from '@ohos.util.ArrayList'; +import { ValueType } from '@ohos.data.ValuesBucket'; + +export class SqlCommand { + sql: string; + rawArguments: Array; + + constructor(sql: string, rawArguments: Array | undefined) { + this.sql = sql; + if(rawArguments == undefined) { + rawArguments = new Array; + } + this.rawArguments = rawArguments; + } + + + // Handle list of int as byte[] + static toValue(value: ValueType): ValueType { + // if(value == null) { + // return null; + // } else { + // // Assume a list is a blob + // if(value instanceof Array) { + // // @SuppressWarnings("unchecked) + // let list: Array = value as Array; + // // let blob; + // Array = new byte[list.length]; + // // for(let i = 0; i < list.length; i++) { + // // blob[i] = list[i]; + // // } + // // value = blob; + // } + // return value; + // } + return value; + } + + public getSql(): string { + return this.sql; + } + + private getSqlArgumentsPrivate(rawArguments: Array): Array { + let fixedArguments = new ArrayList(); + if(rawArguments != null) { + for(let index = 0; index < rawArguments.length; index++) { + const element = rawArguments[index]; + // fixedArguments.add(SqlCommand.toValue(element)); + } + } + // return fixedArguments.toArray(mew Object[0]); + return new Array; + } + + public getSqlArguments(): ValueType[] { + return this.getSqlArgumentsPrivate(this.rawArguments); + } + + public getRawSqlArguments(): Array { + return this.rawArguments; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BaseOperation.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BaseOperation.ets new file mode 100644 index 0000000000000000000000000000000000000000..121907783149ac70d7741844d59f61948565acd2 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BaseOperation.ets @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BaseReadOperation } from './BaseReadOperation'; +import { OperationResult } from './OperationResult'; + +export abstract class BaseOperation extends BaseReadOperation { + protected abstract getOperationResult(): OperationResult; + + success(result: object): void { + this.getOperationResult().success(result); + } + + error(errorCode: string, errorMessage: string, data: object): void { + this.getOperationResult().error(errorCode, errorMessage, data); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BaseReadOperation.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BaseReadOperation.ets new file mode 100644 index 0000000000000000000000000000000000000000..ac82656750a82bb5ba50af03c6ac37de2bdf2312 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BaseReadOperation.ets @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { Constant } from '../Constant'; +import { SqlCommand } from '../SqlCommand'; +import { Operation } from './Operation'; +import { OperationResult } from './OperationResult'; +import { ValueType } from '@ohos.data.ValuesBucket'; + +export abstract class BaseReadOperation implements Operation { + private getSql(): string { + return this.getArgument(Constant.PARAM_SQL); + } + + private getSqlArguments(): Array { + return this.getArgument(Constant.PARAM_SQL_ARGUMENTS); + } + + public getTransactionId(): number | null { + return this.getArgument(Constant.PARAM_TRANSACTION_ID); + } + + public hasNullTransactionId(): boolean { + return this.hasArgument(Constant.PARAM_TRANSACTION_ID) && this.getTransactionId() == null; + } + + public getSqlCommand(): SqlCommand { + return new SqlCommand(this.getSql(), this.getSqlArguments()); + } + + public getInTransactionChange(): Boolean { + return this.getBoolean(Constant.PARAM_IN_TRANSACTION_CHANGE); + } + + getNoResult(): boolean { + if(this.getArgument(Constant.PARAM_NO_RESULT) instanceof Boolean) { + let result: boolean = this.getArgument(Constant.PARAM_NO_RESULT); + return result; + } + return false; + } + + getContinueOnError(): boolean { + if(this.getArgument(Constant.PARAM_CONTINUE_OR_ERROR) instanceof Boolean) { + let result: boolean = this.getArgument(Constant.PARAM_CONTINUE_OR_ERROR); + return result; + } + return false; + } + + private getBoolean(key: string): Boolean { + let value: object = this.getArgument(key); + if(value instanceof Boolean) { + return value; + } + return false; + } + + protected abstract getOperationResult(): OperationResult; + + public toString(): string { + return "" + this.getMethod() + "" + this.getSql() + "" + this.getSqlArguments(); + } + + getMethod(): string { + throw new Error('Method not implemented.'); + } + + getArgument(key: string): T { + throw new Error('Method not implemented.'); + } + + hasArgument(key: string): boolean { + throw new Error('Method not implemented.'); + } + + error(errorCode: string, errorMessage: String, data: object): void { + throw new Error('Method not implemented.'); + } + + success(result: object): void { + throw new Error('Method not implemented.'); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BatchOperation.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BatchOperation.ets new file mode 100644 index 0000000000000000000000000000000000000000..c78c213b9d3693a5f0c7ec7b4f762287783fae16 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/BatchOperation.ets @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import { Constant } from '../Constant'; +import { BaseOperation } from './BaseOperation'; +import { OperationResult } from './OperationResult'; + +export class BatchOperation extends BaseOperation { + private operationResult: BatchOperationResult = new BatchOperationResult(); + public map: Map; + public noResult: boolean; + + constructor(map: Map, noResult: boolean) { + super(); + this.map = map; + this.noResult = noResult; + } + + getMethod(): string { + return this.map.get(Constant.PARAM_METHOD) as string; + } + + getArgument(key: string): T { + return this.map.get(key) as T; + } + + hasArgument(key: string): boolean { + return this.map.has(key); + } + + getOperationResult(): OperationResult { + return this.operationResult; + } + + public getOperationSuccessResult(): Map { + let results: Map = new Map(); + results.set(Constant.PARAM_RESULT, this.operationResult.result); + return results; + } + + public getOperationError(): Map { + let error: Map = new Map(); + let errorDetail: Map = new Map(); + errorDetail.set(Constant.PARAM_ERROR_CODE, this.operationResult.errorCode); + errorDetail.set(Constant.PARAM_ERROR_MESSAGE, this.operationResult.errorMessage); + errorDetail.set(Constant.PARAM_ERROR_DATA, this.operationResult.errorData); + error.set(Constant.PARAM_ERROR_DATA, errorDetail); + return error; + } + + public handleError(result: MethodResult): void { + result.error(this.operationResult.errorCode, this.operationResult.errorMessage, this.operationResult.errorData); + } + + getNoResult(): boolean { + return this.noResult; + } + + public handleSuccess(results: Array>): void { + if(!this.getNoResult()) { + results.push(this.getOperationSuccessResult()); + } + } + + public handleErrorContinue(results: Array>): void { + if(!this.getNoResult()) { + results.push(this.getOperationError()); + } + } +} + +export class BatchOperationResult implements OperationResult { + // success + result: Object | null = null; + // error + errorCode: string = ''; + errorMessage: string = ''; + errorData: Object = ''; + + error(errorCode: string, errorMessage: string, data: Object): void { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.errorData = data; + } + + success(result: Object): void { + this.result = result; + } +} + +export class OperationError { + public errorCode: string; + public errorMessage: string; + public errorData: Object; + + constructor(errorCode: string, errorMessage: string, data: Object) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.errorData = data; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/MethodCallOperation.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/MethodCallOperation.ets new file mode 100644 index 0000000000000000000000000000000000000000..ce97731e1d7d92e9156eb1f887b6ad901d7e9fb4 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/MethodCallOperation.ets @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; +import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import { BaseOperation } from './BaseOperation'; +import { OperationResult } from './OperationResult'; + +export class MethodCallOperation extends BaseOperation { + public result: Result; + private methodCall: MethodCall; + + constructor(methodCall: MethodCall, result: MethodResult) { + super(); + this.methodCall = methodCall; + this.result = new Result(result); + } + + getMethod(): string { + return this.methodCall.method; + } + + getArgument(key: string): T { + return this.methodCall.argument(key); + } + + hasArgument(key: string): boolean { + return this.methodCall.hasArgument(key); + } + + protected getOperationResult(): OperationResult { + return this.result; + } +} + +class Result implements OperationResult { + private result: MethodResult; + + constructor(result: MethodResult) { + this.result = result; + } + + success(result: Object): void { + this.result.success(result); + } + + error(errorCode: string, errorMessage: string, data: Object): void { + this.result.error(errorCode, errorMessage, data); + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/Operation.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/Operation.ets new file mode 100644 index 0000000000000000000000000000000000000000..b6b01f47349a38d4a38741c969dea8a2bfc28126 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/Operation.ets @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { SqlCommand } from '../SqlCommand'; +import { OperationResult } from './OperationResult'; + +export interface Operation extends OperationResult { + getMethod(): string; + + getArgument(key: string): T; + + hasArgument(key: string): boolean; + + getSqlCommand(): SqlCommand; + + getNoResult(): boolean; + + // In batch, means ignoring the error + getContinueOnError(): boolean; + + // Only for execute command, true when entering a transaction, false when exiting + getInTransactionChange(): Boolean; + + /** + * transaction id if any, only for within a transaction + */ + getTransactionId(): number | null; + + /** + * Transaction v2 support + */ + hasNullTransactionId(): boolean; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/OperationResult.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/OperationResult.ets new file mode 100644 index 0000000000000000000000000000000000000000..4515fb64f166286ed745802c83be2eb32fbbb2e9 --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/OperationResult.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export interface OperationResult { + error(errorCode: string, errorMessage: string, data: Object): void; + + success(result: Object | null): void; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/OperationRunnable.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/OperationRunnable.ets new file mode 100644 index 0000000000000000000000000000000000000000..2912e11067b00352845d4c7bbe7472c368cf935e --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/OperationRunnable.ets @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +export interface OperationRunnable { + run(): boolean; +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/SqlErrorInfo.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/SqlErrorInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..868fd930bda7b6d55822bc8ac45df34af7c5e72f --- /dev/null +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/operation/SqlErrorInfo.ets @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { Constant } from '../constant'; +import { SqlCommand } from '../SqlCommand'; +import { Operation } from './Operation'; + +export class SqlErrorInfo { + public static getMap(operation: Operation): Map { + let map: Map = new Map(); + let command: SqlCommand = operation.getSqlCommand(); + if(command != null) { + map.set(Constant.PARAM_SQL, command.getSql()); + map.set(Constant.PARAM_SQL_ARGUMENTS, command.getRawSqlArguments()); + } + return map; + } +} \ No newline at end of file diff --git a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets index 84a7a745317c433782c09002654d15706346fb0c..101efed5f9abd208c0b5581a18c1db6f4c6b604f 100644 --- a/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets +++ b/sqflite/ohos/sqflite/src/main/ets/io/flutter/plugins/sqflite/sqflite_helper.ets @@ -239,12 +239,41 @@ export class SqfLiteHelper { let dbNameList: string[] = dataBaseName.split('/'); let dbName: string = dbNameList[dbNameList.length - 1]; let endWithDb: boolean = Tools.stringEndWith(dbName, '.db'); - Log.i(TAG, 'step:-1 delete asction, got database name:' + dataBaseName + 'endWithDb:' + endWithDb); + Log.i(TAG, 'step:-1 delete action, got database name:' + dataBaseName + 'endWithDb:' + endWithDb); if (!endWithDb) { dbName = dbName + '.db'; + dataBaseName = dataBaseName + '.db'; } - dataBaseName = dbName; + Log.i(TAG, 'step:0 delete action, got database name:' + dataBaseName + 'endWithDb:' + endWithDb); + + //自定义数据库路径 + let customDir: string = ''; + for (let index = 5; index < dbNameList.length - 1; index++) { + if (customDir.length > 0) { + customDir = customDir + '/' + dbNameList[index]; + } else { + customDir = dbNameList[index]; + } + } + + Log.i(TAG, '~~custom db Dir: ' + customDir + ' system version:' + deviceInfo.osFullName, ''); + + // 从系统中获取 + let config: relationalStore.StoreConfig; + if (customDir.length > 0) { + config = { + name: dbName, // 数据库文件名 + securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别 + customDir: customDir, + }; + } else { + config = { + name: dbName, // 数据库文件名 + securityLevel: relationalStore.SecurityLevel.S1, // 数据库安全级别 + } + } + if (SqfLiteHelper.dataBaseList.has(dataBaseName)) { Log.i(TAG, 'step:1 already loaded database, trying delete' + dataBaseName); SqfLiteHelper.dataBaseList.delete(dataBaseName); @@ -256,10 +285,11 @@ export class SqfLiteHelper { }) if (id > -1) { SqfLiteHelper.dBIdList.delete(id); - await relationalStore.deleteRdbStore(context, dataBaseName); - Log.i(TAG, 'step:2 already deleted ' + dataBaseName + ' 数据库', '%{public}s'); + await relationalStore.deleteRdbStore(context, config); result = true; + return result; } + return result; } else { Log.i(TAG, 'step:3 unload database, trying delete' + dataBaseName); try { @@ -267,15 +297,16 @@ export class SqfLiteHelper { if (await SqfLiteHelper.checkTable(dataBaseName, 'defaultTable') == true) { await SqfLiteHelper.deleteTable(dataBaseName, 'defaultTable'); } - await relationalStore.deleteRdbStore(context, dataBaseName); - Log.i(TAG, 'step:4 already deleted ' + dataBaseName + ' 数据库', '%{public}s'); + + await relationalStore.deleteRdbStore(context, config); result = true; + return result; } catch (e) { Log.i(TAG, 'step:5 deleted database error' + e, '%{public}s'); + return result; } } - // Log.i(TAG, 'can not found this database, delete faired', '%{public}s'); - return result; + } public static async insert(call: MethodCall, result: MethodResult, dataBase: relationalStore.RdbStore): Promise {