go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/postgresql/namespace.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package postgresql 26 27 import ( 28 "context" 29 "database/sql" 30 "errors" 31 32 "go.temporal.io/api/serviceerror" 33 34 "go.temporal.io/server/common/persistence/sql/sqlplugin" 35 ) 36 37 const ( 38 createNamespaceQuery = `INSERT INTO 39 namespaces (partition_id, id, name, is_global, data, data_encoding, notification_version) 40 VALUES($1, $2, $3, $4, $5, $6, $7)` 41 42 updateNamespaceQuery = `UPDATE namespaces 43 SET name = $1, data = $2, data_encoding = $3, is_global = $4, notification_version = $5 44 WHERE partition_id=54321 AND id = $6` 45 46 getNamespacePart = `SELECT id, name, is_global, data, data_encoding, notification_version FROM namespaces` 47 48 getNamespaceByIDQuery = getNamespacePart + ` WHERE partition_id=$1 AND id = $2` 49 getNamespaceByNameQuery = getNamespacePart + ` WHERE partition_id=$1 AND name = $2` 50 51 listNamespacesQuery = getNamespacePart + ` WHERE partition_id=$1 ORDER BY id LIMIT $2` 52 listNamespacesRangeQuery = getNamespacePart + ` WHERE partition_id=$1 AND id > $2 ORDER BY id LIMIT $3` 53 54 deleteNamespaceByIDQuery = `DELETE FROM namespaces WHERE partition_id=$1 AND id = $2` 55 deleteNamespaceByNameQuery = `DELETE FROM namespaces WHERE partition_id=$1 AND name = $2` 56 57 getNamespaceMetadataQuery = `SELECT notification_version FROM namespace_metadata WHERE partition_id=$1` 58 lockNamespaceMetadataQuery = `SELECT notification_version FROM namespace_metadata WHERE partition_id=$1 FOR UPDATE` 59 updateNamespaceMetadataQuery = `UPDATE namespace_metadata SET notification_version = $1 WHERE notification_version = $2 AND partition_id=$3` 60 ) 61 62 const ( 63 partitionID = 54321 64 ) 65 66 var errMissingArgs = errors.New("missing one or more args for API") 67 68 // InsertIntoNamespace inserts a single row into namespaces table 69 func (pdb *db) InsertIntoNamespace( 70 ctx context.Context, 71 row *sqlplugin.NamespaceRow, 72 ) (sql.Result, error) { 73 return pdb.conn.ExecContext(ctx, createNamespaceQuery, partitionID, row.ID, row.Name, row.IsGlobal, row.Data, row.DataEncoding, row.NotificationVersion) 74 } 75 76 // UpdateNamespace updates a single row in namespaces table 77 func (pdb *db) UpdateNamespace( 78 ctx context.Context, 79 row *sqlplugin.NamespaceRow, 80 ) (sql.Result, error) { 81 return pdb.conn.ExecContext(ctx, updateNamespaceQuery, row.Name, row.Data, row.DataEncoding, row.IsGlobal, row.NotificationVersion, row.ID) 82 } 83 84 // SelectFromNamespace reads one or more rows from namespaces table 85 func (pdb *db) SelectFromNamespace( 86 ctx context.Context, 87 filter sqlplugin.NamespaceFilter, 88 ) ([]sqlplugin.NamespaceRow, error) { 89 switch { 90 case filter.ID != nil || filter.Name != nil: 91 if filter.ID != nil && filter.Name != nil { 92 return nil, serviceerror.NewInternal("only ID or name filter can be specified for selection") 93 } 94 return pdb.selectFromNamespace(ctx, filter) 95 case filter.PageSize != nil && *filter.PageSize > 0: 96 return pdb.selectAllFromNamespace(ctx, filter) 97 default: 98 return nil, errMissingArgs 99 } 100 } 101 102 func (pdb *db) selectFromNamespace( 103 ctx context.Context, 104 filter sqlplugin.NamespaceFilter, 105 ) ([]sqlplugin.NamespaceRow, error) { 106 var err error 107 var row sqlplugin.NamespaceRow 108 switch { 109 case filter.ID != nil: 110 err = pdb.conn.GetContext(ctx, 111 &row, 112 getNamespaceByIDQuery, 113 partitionID, 114 *filter.ID, 115 ) 116 case filter.Name != nil: 117 err = pdb.conn.GetContext(ctx, 118 &row, 119 getNamespaceByNameQuery, 120 partitionID, 121 *filter.Name, 122 ) 123 } 124 if err != nil { 125 return nil, err 126 } 127 return []sqlplugin.NamespaceRow{row}, nil 128 } 129 130 func (pdb *db) selectAllFromNamespace( 131 ctx context.Context, 132 filter sqlplugin.NamespaceFilter, 133 ) ([]sqlplugin.NamespaceRow, error) { 134 var err error 135 var rows []sqlplugin.NamespaceRow 136 switch { 137 case filter.GreaterThanID != nil: 138 err = pdb.conn.SelectContext(ctx, 139 &rows, 140 listNamespacesRangeQuery, 141 partitionID, 142 *filter.GreaterThanID, 143 *filter.PageSize, 144 ) 145 default: 146 err = pdb.conn.SelectContext(ctx, 147 &rows, 148 listNamespacesQuery, 149 partitionID, 150 filter.PageSize, 151 ) 152 } 153 return rows, err 154 } 155 156 // DeleteFromNamespace deletes a single row in namespaces table 157 func (pdb *db) DeleteFromNamespace( 158 ctx context.Context, 159 filter sqlplugin.NamespaceFilter, 160 ) (sql.Result, error) { 161 var err error 162 var result sql.Result 163 switch { 164 case filter.ID != nil: 165 result, err = pdb.conn.ExecContext(ctx, 166 deleteNamespaceByIDQuery, 167 partitionID, 168 filter.ID, 169 ) 170 default: 171 result, err = pdb.conn.ExecContext(ctx, 172 deleteNamespaceByNameQuery, 173 partitionID, 174 filter.Name, 175 ) 176 } 177 return result, err 178 } 179 180 // LockNamespaceMetadata acquires a write lock on a single row in namespace_metadata table 181 func (pdb *db) LockNamespaceMetadata( 182 ctx context.Context, 183 ) (*sqlplugin.NamespaceMetadataRow, error) { 184 var row sqlplugin.NamespaceMetadataRow 185 err := pdb.conn.GetContext(ctx, 186 &row.NotificationVersion, 187 lockNamespaceMetadataQuery, 188 partitionID, 189 ) 190 if err != nil { 191 return nil, err 192 } 193 return &row, nil 194 } 195 196 // SelectFromNamespaceMetadata reads a single row in namespace_metadata table 197 func (pdb *db) SelectFromNamespaceMetadata( 198 ctx context.Context, 199 ) (*sqlplugin.NamespaceMetadataRow, error) { 200 var row sqlplugin.NamespaceMetadataRow 201 err := pdb.conn.GetContext(ctx, 202 &row.NotificationVersion, 203 getNamespaceMetadataQuery, 204 partitionID, 205 ) 206 return &row, err 207 } 208 209 // UpdateNamespaceMetadata updates a single row in namespace_metadata table 210 func (pdb *db) UpdateNamespaceMetadata( 211 ctx context.Context, 212 row *sqlplugin.NamespaceMetadataRow, 213 ) (sql.Result, error) { 214 return pdb.conn.ExecContext(ctx, 215 updateNamespaceMetadataQuery, 216 row.NotificationVersion+1, 217 row.NotificationVersion, 218 partitionID, 219 ) 220 }