1 /*
2 * Copyright (c) 2023 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 */
15
16 #include "cloud_sync_log_table_manager.h"
17
18 namespace DistributedDB {
CalcPrimaryKeyHash(const std::string & references,const TableInfo & table,const std::string & identity)19 std::string CloudSyncLogTableManager::CalcPrimaryKeyHash(const std::string &references, const TableInfo &table,
20 const std::string &identity)
21 {
22 (void)identity;
23 std::string sql;
24 if (table.GetPrimaryKey().size() == 1) {
25 sql = "calc_hash(" + references + "'" + table.GetPrimaryKey().at(0) + "')";
26 } else {
27 std::set<std::string> primaryKeySet; // we need sort primary key by name
28 for (const auto &it : table.GetPrimaryKey()) {
29 primaryKeySet.emplace(it.second);
30 }
31 sql = "calc_hash(";
32 for (const auto &it : primaryKeySet) {
33 sql += "calc_hash(" + references + "'" + it + "')||";
34 }
35 sql.pop_back();
36 sql.pop_back();
37 sql += ")";
38 }
39 return sql;
40 }
41
GetIndexSql(const TableInfo & table,std::vector<std::string> & schema)42 void CloudSyncLogTableManager::GetIndexSql(const TableInfo &table, std::vector<std::string> &schema)
43 {
44 const std::string tableName = GetLogTableName(table);
45
46 std::string indexTimestampFlagGid = "CREATE INDEX IF NOT EXISTS " + tableName +
47 "_cloud_time_flag_gid_index ON " + tableName + "(timestamp, flag, cloud_gid);";
48 std::string indexGid = "CREATE INDEX IF NOT EXISTS " + tableName +
49 "_cloud_gid_index ON " + tableName + "(cloud_gid);";
50 schema.emplace_back(indexTimestampFlagGid);
51 schema.emplace_back(indexGid);
52 }
53
GetPrimaryKeySql(const TableInfo & table)54 std::string CloudSyncLogTableManager::GetPrimaryKeySql(const TableInfo &table)
55 {
56 return "PRIMARY KEY(hash_key)";
57 }
58
59 // The parameter "identity" is a hash string that identifies a device. The same for the next two functions.
GetInsertTrigger(const TableInfo & table,const std::string & identity)60 std::string CloudSyncLogTableManager::GetInsertTrigger(const TableInfo &table, const std::string &identity)
61 {
62 std::string logTblName = GetLogTableName(table);
63 std::string insertTrigger = "CREATE TRIGGER IF NOT EXISTS ";
64 insertTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_INSERT AFTER INSERT \n";
65 insertTrigger += "ON '" + table.GetTableName() + "'\n";
66 insertTrigger += "WHEN (SELECT count(*) from " + DBConstant::RELATIONAL_PREFIX + "metadata ";
67 insertTrigger += "WHERE key = 'log_trigger_switch' AND value = 'true')\n";
68 insertTrigger += "BEGIN\n";
69 insertTrigger += "\t INSERT OR REPLACE INTO " + logTblName;
70 insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key, cloud_gid)";
71 insertTrigger += " VALUES (new.rowid, '', '',";
72 insertTrigger += " get_raw_sys_time(), get_raw_sys_time(), 0x02, ";
73 insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", CASE WHEN (SELECT count(*)<>0 FROM ";
74 insertTrigger += logTblName + " where hash_key = " + CalcPrimaryKeyHash("NEW.", table, identity);
75 insertTrigger += ") THEN (select cloud_gid from " + logTblName + " where hash_key = ";
76 insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ") ELSE '' END);\n";
77 insertTrigger += "END;";
78 return insertTrigger;
79 }
80
GetUpdateTrigger(const TableInfo & table,const std::string & identity)81 std::string CloudSyncLogTableManager::GetUpdateTrigger(const TableInfo &table, const std::string &identity)
82 {
83 (void)identity;
84 std::string logTblName = GetLogTableName(table);
85 std::string updateTrigger = "CREATE TRIGGER IF NOT EXISTS ";
86 updateTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_UPDATE AFTER UPDATE \n";
87 updateTrigger += "ON '" + table.GetTableName() + "'\n";
88 updateTrigger += "WHEN (SELECT count(*) from " + DBConstant::RELATIONAL_PREFIX + "metadata ";
89 updateTrigger += "WHERE key = 'log_trigger_switch' AND value = 'true')\n";
90 updateTrigger += "BEGIN\n"; // if user change the primary key, we can still use gid to identify which one is updated
91 updateTrigger += "\t UPDATE " + logTblName;
92 updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02";
93 updateTrigger += " WHERE data_key = OLD.rowid;\n";
94 updateTrigger += "END;";
95 return updateTrigger;
96 }
97
GetDeleteTrigger(const TableInfo & table,const std::string & identity)98 std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity)
99 {
100 (void)identity;
101 std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS ";
102 deleteTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_DELETE BEFORE DELETE \n";
103 deleteTrigger += "ON '" + table.GetTableName() + "'\n";
104 deleteTrigger += "WHEN (SELECT count(*) from " + DBConstant::RELATIONAL_PREFIX + "metadata ";
105 deleteTrigger += "WHERE key = 'log_trigger_switch' AND VALUE = 'true')\n";
106 deleteTrigger += "BEGIN\n";
107 deleteTrigger += "\t UPDATE " + GetLogTableName(table);
108 deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()";
109 deleteTrigger += " WHERE data_key = OLD.rowid;";
110 deleteTrigger += "END;";
111 return deleteTrigger;
112 }
113 } // DistributedDB