1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import dataRdb from '@ohos.data.rdb' 16import featureAbility from '@ohos.ability.featureAbility' 17import Contact from '../model/Contact' 18import Logger from '../model/Logger' 19import { TABLE_NAME, SQL_CREATE_TABLE, COLUMNS, STORE_CONFIG } from '../model/RdbConst' 20 21const TAG = 'RdbModel' 22 23class RdbModel { 24 private rdbStore: dataRdb.RdbStore = undefined 25 private tableName: string = '' 26 private sqlCreateTable: string = '' 27 private columns: Array<string> = [] 28 private distributedTable: string = '' 29 private dataChangeCallback = null 30 private isCreateDbDone: boolean = false 31 32 constructor(tableName: string, sqlCreateTable: string, columns: Array<string>) { 33 this.tableName = tableName 34 this.sqlCreateTable = sqlCreateTable 35 this.columns = columns 36 } 37 38 async getRdbStore() { 39 Logger.info(TAG, 'getRdbStore begin') 40 if (this.isCreateDbDone) { 41 return 42 } 43 this.rdbStore = await dataRdb.getRdbStore(featureAbility.getContext(), STORE_CONFIG, 1) 44 Logger.info(TAG, 'getRdbStore end') 45 await this.rdbStore.executeSql(this.sqlCreateTable) 46 await this.rdbStore.setDistributedTables([this.tableName]) 47 this.isCreateDbDone = true 48 Logger.info(TAG, 'create table done') 49 } 50 51 async insertData(contact: Contact) { 52 const valueBucket = { 53 'name': contact.name, 54 'gender': contact.gender, 55 'phone': contact.phone, 56 'remark': contact.remark 57 } 58 let ret = await this.rdbStore.insert(this.tableName, valueBucket) 59 Logger.info(TAG, `insert done:${ret}`) 60 } 61 62 async updateData(contact: Contact) { 63 const valueBucket = { 64 'name': contact.name, 65 'gender': contact.gender, 66 'phone': contact.phone, 67 'remark': contact.remark 68 } 69 let predicates = new dataRdb.RdbPredicates(this.tableName) 70 Logger.info(TAG, `updateData id=${contact.id}`) 71 predicates.equalTo('id', contact.id) 72 let ret = await this.rdbStore.update(valueBucket, predicates) 73 Logger.info(TAG, `updated row count: ${ret}`) 74 } 75 76 async deleteContacts(contacts: Array<Contact>) { 77 let predicates = new dataRdb.RdbPredicates(this.tableName) 78 contacts.forEach((contact) => { 79 predicates.or() 80 .equalTo('id', contact.id) 81 }) 82 let rows = await this.rdbStore.delete(predicates) 83 Logger.info(TAG, `delete rows: ${rows}`) 84 } 85 86 async query(predicates) { 87 Logger.info(TAG, 'query start') 88 let resultSet = await this.rdbStore.query(predicates, this.columns) 89 return this.getListFromResultSet(resultSet) 90 } 91 92 async syncData(predicates) { 93 Logger.info(TAG, 'syncData') 94 let result = await this.rdbStore.sync(dataRdb.SyncMode.SYNC_MODE_PUSH, predicates) 95 for (let i = 0; i < result.length; i++) { 96 Logger.info(TAG, `device=${result[i][0]}, status = ${result[i][1]}`) 97 } 98 } 99 100 async onDataChange(device, callback) { 101 this.distributedTable = await this.rdbStore.obtainDistributedTableName(device, this.tableName) 102 Logger.info(TAG, `obtainDistributedTableName,distributedTable=` + this.distributedTable) 103 this.dataChangeCallback = callback 104 await this.pullData() 105 this.rdbStore.on('dataChange', dataRdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, async (devices) => { 106 Logger.info(TAG, `on dataChange, callback`) 107 await this.pullData() 108 }) 109 } 110 111 async pullData() { 112 await this.rdbStore.executeSql('delete from ' + this.tableName) 113 let predicates = new dataRdb.RdbPredicates(this.distributedTable) 114 let resultSet = await this.rdbStore.query(predicates, this.columns) 115 let result = this.getListFromResultSet(resultSet) 116 Logger.info(TAG, `on dataChange,result.length=${result.length}`) 117 for (let i = 0; i < result.length; i++) { 118 Logger.info(TAG, `on dataChange,insert${result[i].name}`) 119 let predicate = new dataRdb.RdbPredicates(this.tableName) 120 predicate.equalTo('name', result[i].name) 121 let exit = await this.rdbStore.query(predicate, this.columns) 122 exit.goToFirstRow() 123 if (exit.rowCount === 0) { 124 await this.insertData(result[i]) 125 } else { 126 result[i].id = exit.getDouble(resultSet.getColumnIndex('id')) 127 await this.updateData(result[i]) 128 } 129 } 130 this.dataChangeCallback(result) 131 } 132 133 offDataChange() { 134 this.rdbStore.off('dataChange', dataRdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, (devices) => { 135 for (let i = 0; i < devices.length; i++) { 136 Logger.info(TAG, `device=${devices[i]} off data changed`) 137 } 138 }) 139 } 140 141 getListFromResultSet(resultSet) { 142 Logger.info(TAG, 'getListFromResultSet') 143 let contacts: Array<Contact> = [] 144 Logger.info(TAG, `resultSet column names:${resultSet.columnNames}`) 145 Logger.info(TAG, `row count:${resultSet.rowCount}`) 146 Logger.info(TAG, `resultSet goToFirstRow:${resultSet.goToFirstRow()}`) 147 while (!resultSet.isEnded) { 148 let contact = new Contact(resultSet.getDouble(resultSet.getColumnIndex('id')) 149 , resultSet.getString(resultSet.getColumnIndex('name')) 150 , resultSet.getDouble(resultSet.getColumnIndex('gender')) 151 , resultSet.getString(resultSet.getColumnIndex('phone')) 152 , resultSet.getString(resultSet.getColumnIndex('remark'))) 153 if (!contacts.includes(contact)) { 154 contacts.push(contact) 155 } 156 resultSet.goToNextRow() 157 } 158 resultSet.close() 159 return contacts 160 } 161} 162 163export default new RdbModel(TABLE_NAME, SQL_CREATE_TABLE, COLUMNS)