go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/sqlite/events.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2021 Datadog, Inc. 4 // 5 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 6 // 7 // Copyright (c) 2020 Uber Technologies, Inc. 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining a copy 10 // of this software and associated documentation files (the "Software"), to deal 11 // in the Software without restriction, including without limitation the rights 12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 // copies of the Software, and to permit persons to whom the Software is 14 // furnished to do so, subject to the following conditions: 15 // 16 // The above copyright notice and this permission notice shall be included in 17 // all copies or substantial portions of the Software. 18 // 19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 // THE SOFTWARE. 26 27 package sqlite 28 29 import ( 30 "context" 31 "database/sql" 32 33 "go.temporal.io/server/common/persistence/sql/sqlplugin" 34 ) 35 36 const ( 37 // below are templates for history_node table 38 replaceHistoryNodesQuery = `REPLACE INTO history_node (` + 39 `shard_id, tree_id, branch_id, node_id, prev_txn_id, txn_id, data, data_encoding) ` + 40 `VALUES (:shard_id, :tree_id, :branch_id, :node_id, :prev_txn_id, :txn_id, :data, :data_encoding) ` 41 42 getHistoryNodesQuery = `SELECT node_id, prev_txn_id, txn_id, data, data_encoding FROM history_node ` + 43 `WHERE shard_id = ? AND tree_id = ? AND branch_id = ? AND ((node_id = ? AND txn_id > ?) OR node_id > ?) AND node_id < ? ` + 44 `ORDER BY shard_id, tree_id, branch_id, node_id, txn_id LIMIT ? ` 45 46 getHistoryNodesReverseQuery = `SELECT node_id, prev_txn_id, txn_id, data, data_encoding FROM history_node ` + 47 `WHERE shard_id = ? AND tree_id = ? AND branch_id = ? AND node_id >= ? AND ((node_id = ? AND txn_id < ?) OR node_id < ?) ` + 48 `ORDER BY shard_id, tree_id, branch_id DESC, node_id DESC, txn_id DESC LIMIT ? ` 49 50 getHistoryNodeMetadataQuery = `SELECT node_id, prev_txn_id, txn_id FROM history_node ` + 51 `WHERE shard_id = ? AND tree_id = ? AND branch_id = ? AND ((node_id = ? AND txn_id > ?) OR node_id > ?) AND node_id < ? ` + 52 `ORDER BY shard_id, tree_id, branch_id, node_id, txn_id LIMIT ? ` 53 54 deleteHistoryNodeQuery = `DELETE FROM history_node WHERE shard_id = ? AND tree_id = ? AND branch_id = ? AND node_id = ? AND txn_id = ? ` 55 56 deleteHistoryNodesQuery = `DELETE FROM history_node WHERE shard_id = ? AND tree_id = ? AND branch_id = ? AND node_id >= ? ` 57 58 // below are templates for history_tree table 59 addHistoryTreeQuery = `REPLACE INTO history_tree (` + 60 `shard_id, tree_id, branch_id, data, data_encoding) ` + 61 `VALUES (:shard_id, :tree_id, :branch_id, :data, :data_encoding) ` 62 63 getHistoryTreeQuery = `SELECT branch_id, data, data_encoding FROM history_tree WHERE shard_id = ? AND tree_id = ? ` 64 65 paginateBranchesQuery = `SELECT shard_id, tree_id, branch_id, data, data_encoding 66 FROM history_tree 67 WHERE (shard_id, tree_id, branch_id) > ($1, $2, $3) 68 ORDER BY shard_id, tree_id, branch_id 69 LIMIT $4` 70 71 deleteHistoryTreeQuery = `DELETE FROM history_tree WHERE shard_id = ? AND tree_id = ? AND branch_id = ? ` 72 ) 73 74 // For history_node table: 75 76 // InsertIntoHistoryNode inserts a row into history_node table 77 func (mdb *db) InsertIntoHistoryNode( 78 ctx context.Context, 79 row *sqlplugin.HistoryNodeRow, 80 ) (sql.Result, error) { 81 // NOTE: txn_id is *= -1 within DB 82 row.TxnID = -row.TxnID 83 return mdb.conn.NamedExecContext(ctx, 84 replaceHistoryNodesQuery, 85 row, 86 ) 87 } 88 89 // DeleteFromHistoryNode delete a row from history_node table 90 func (mdb *db) DeleteFromHistoryNode( 91 ctx context.Context, 92 row *sqlplugin.HistoryNodeRow, 93 ) (sql.Result, error) { 94 // NOTE: txn_id is *= -1 within DB 95 row.TxnID = -row.TxnID 96 return mdb.conn.ExecContext(ctx, 97 deleteHistoryNodeQuery, 98 row.ShardID, 99 row.TreeID, 100 row.BranchID, 101 row.NodeID, 102 row.TxnID, 103 ) 104 } 105 106 // SelectFromHistoryNode reads one or more rows from history_node table 107 func (mdb *db) RangeSelectFromHistoryNode( 108 ctx context.Context, 109 filter sqlplugin.HistoryNodeSelectFilter, 110 ) ([]sqlplugin.HistoryNodeRow, error) { 111 var query string 112 if filter.MetadataOnly { 113 query = getHistoryNodeMetadataQuery 114 } else if filter.ReverseOrder { 115 query = getHistoryNodesReverseQuery 116 } else { 117 query = getHistoryNodesQuery 118 } 119 120 var args []interface{} 121 if filter.ReverseOrder { 122 args = []interface{}{ 123 filter.ShardID, 124 filter.TreeID, 125 filter.BranchID, 126 filter.MinNodeID, 127 filter.MaxTxnID, 128 -filter.MaxTxnID, 129 filter.MaxNodeID, 130 filter.PageSize, 131 } 132 } else { 133 args = []interface{}{ 134 filter.ShardID, 135 filter.TreeID, 136 filter.BranchID, 137 filter.MinNodeID, 138 -filter.MinTxnID, // NOTE: transaction ID is *= -1 when stored 139 filter.MinNodeID, 140 filter.MaxNodeID, 141 filter.PageSize, 142 } 143 } 144 145 var rows []sqlplugin.HistoryNodeRow 146 if err := mdb.conn.SelectContext(ctx, &rows, query, args...); err != nil { 147 return nil, err 148 } 149 150 for index := range rows { 151 rows[index].TxnID = -rows[index].TxnID 152 } 153 154 return rows, nil 155 } 156 157 // DeleteFromHistoryNode deletes one or more rows from history_node table 158 func (mdb *db) RangeDeleteFromHistoryNode( 159 ctx context.Context, 160 filter sqlplugin.HistoryNodeDeleteFilter, 161 ) (sql.Result, error) { 162 return mdb.conn.ExecContext(ctx, 163 deleteHistoryNodesQuery, 164 filter.ShardID, 165 filter.TreeID, 166 filter.BranchID, 167 filter.MinNodeID, 168 ) 169 } 170 171 // For history_tree table: 172 173 // InsertIntoHistoryTree inserts a row into history_tree table 174 func (mdb *db) InsertIntoHistoryTree( 175 ctx context.Context, 176 row *sqlplugin.HistoryTreeRow, 177 ) (sql.Result, error) { 178 return mdb.conn.NamedExecContext(ctx, 179 addHistoryTreeQuery, 180 row, 181 ) 182 } 183 184 // SelectFromHistoryTree reads one or more rows from history_tree table 185 func (mdb *db) SelectFromHistoryTree( 186 ctx context.Context, 187 filter sqlplugin.HistoryTreeSelectFilter, 188 ) ([]sqlplugin.HistoryTreeRow, error) { 189 var rows []sqlplugin.HistoryTreeRow 190 err := mdb.conn.SelectContext(ctx, 191 &rows, 192 getHistoryTreeQuery, 193 filter.ShardID, 194 filter.TreeID, 195 ) 196 return rows, err 197 } 198 199 // PaginateBranchesFromHistoryTree reads up to page.Limit rows from the history_tree table sorted by their primary key, 200 // while skipping the first page.Offset rows. 201 func (mdb *db) PaginateBranchesFromHistoryTree( 202 ctx context.Context, 203 page sqlplugin.HistoryTreeBranchPage, 204 ) ([]sqlplugin.HistoryTreeRow, error) { 205 var rows []sqlplugin.HistoryTreeRow 206 err := mdb.conn.SelectContext(ctx, 207 &rows, 208 paginateBranchesQuery, 209 page.ShardID, 210 page.TreeID, 211 page.BranchID, 212 page.Limit, 213 ) 214 return rows, err 215 } 216 217 // DeleteFromHistoryTree deletes one or more rows from history_tree table 218 func (mdb *db) DeleteFromHistoryTree( 219 ctx context.Context, 220 filter sqlplugin.HistoryTreeDeleteFilter, 221 ) (sql.Result, error) { 222 return mdb.conn.ExecContext(ctx, 223 deleteHistoryTreeQuery, 224 filter.ShardID, 225 filter.TreeID, 226 filter.BranchID, 227 ) 228 }