1 /*
2 * Copyright (c) 2021 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 "split_device_log_table_manager.h"
17
18 namespace DistributedDB {
CalcPrimaryKeyHash(const std::string & references,const TableInfo & table,const std::string & identity)19 std::string SplitDeviceLogTableManager::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 sql = "calc_hash(";
28 for (const auto &it : table.GetPrimaryKey()) {
29 sql += "calc_hash(" + references + "'" + it.second + "')||";
30 }
31 sql.pop_back();
32 sql.pop_back();
33 sql += ")";
34 }
35 return sql;
36 }
37
GetInsertTrigger(const TableInfo & table,const std::string & identity)38 std::string SplitDeviceLogTableManager::GetInsertTrigger(const TableInfo &table, const std::string &identity)
39 {
40 std::string logTblName = DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log";
41 std::string insertTrigger = "CREATE TRIGGER IF NOT EXISTS ";
42 insertTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_INSERT AFTER INSERT \n";
43 insertTrigger += "ON '" + table.GetTableName() + "'\n";
44 insertTrigger += "BEGIN\n";
45 insertTrigger += "\t INSERT OR REPLACE INTO " + logTblName;
46 insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key)";
47 insertTrigger += " VALUES (new.rowid, '', '',";
48 insertTrigger += " get_sys_time(0), get_last_time(),";
49 insertTrigger += " CASE WHEN (SELECT count(*)<>0 FROM " + logTblName + " WHERE hash_key=" +
50 CalcPrimaryKeyHash("NEW.", table, identity) + " AND flag&0x02=0x02) THEN 0x22 ELSE 0x02 END,";
51 insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ");\n";
52 insertTrigger += "END;";
53 return insertTrigger;
54 }
55
GetUpdateTrigger(const TableInfo & table,const std::string & identity)56 std::string SplitDeviceLogTableManager::GetUpdateTrigger(const TableInfo &table, const std::string &identity)
57 {
58 std::string logTblName = DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log";
59 std::string updateTrigger = "CREATE TRIGGER IF NOT EXISTS ";
60 updateTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_UPDATE AFTER UPDATE \n";
61 updateTrigger += "ON '" + table.GetTableName() + "'\n";
62 updateTrigger += "BEGIN\n";
63 if (table.GetPrimaryKey().size() == 1 && table.GetPrimaryKey().at(0) == "rowid") {
64 // primary key is rowid, it can't be changed
65 updateTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log";
66 updateTrigger += " SET timestamp=get_sys_time(0), device='', flag=0x22";
67 updateTrigger += " WHERE hash_key=" + CalcPrimaryKeyHash("OLD.", table, identity) +
68 " AND flag&0x02=0x02;\n";
69 } else {
70 // primary key may be changed, so we need to set the old log record deleted, then insert or replace a new
71 // log record(if primary key not change, insert or replace will modify the log record we set deleted in previous
72 // step)
73 updateTrigger += "\t UPDATE " + logTblName;
74 updateTrigger += " SET data_key=-1,timestamp=get_sys_time(0), device='', flag=0x03";
75 updateTrigger += " WHERE hash_key=" + CalcPrimaryKeyHash("OLD.", table, identity) + " AND flag&0x02=0x02;\n";
76 updateTrigger += "\t INSERT OR REPLACE INTO " + logTblName + " VALUES (NEW.rowid, '', '', get_sys_time(0), "
77 "get_last_time(), CASE WHEN (" + CalcPrimaryKeyHash("NEW.", table, identity) + " != " +
78 CalcPrimaryKeyHash("NEW.", table, identity) + ") THEN 0x02 ELSE 0x22 END, " +
79 CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n";
80 }
81 updateTrigger += "END;";
82 return updateTrigger;
83 }
84
GetDeleteTrigger(const TableInfo & table,const std::string & identity)85 std::string SplitDeviceLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity)
86 {
87 std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS ";
88 deleteTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_DELETE BEFORE DELETE \n";
89 deleteTrigger += "ON '" + table.GetTableName() + "'\n";
90 deleteTrigger += "BEGIN\n";
91 deleteTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log";
92 deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_sys_time(0)";
93 deleteTrigger += " WHERE hash_key=" + CalcPrimaryKeyHash("OLD.", table, identity) +
94 " AND flag&0x02=0x02;\n";
95 deleteTrigger += "END;";
96 return deleteTrigger;
97 }
98
GetPrimaryKeySql(const TableInfo & table)99 std::string SplitDeviceLogTableManager::GetPrimaryKeySql(const TableInfo &table)
100 {
101 return "PRIMARY KEY(device, hash_key)";
102 }
103 }