blob: 42d329206980aee846711a6bc012c96275ecc42e [file] [log] [blame]
package sqlreversekeymapstore
import (
"context"
"github.com/jackc/pgx/v4"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/go/sql/pool"
"go.skia.org/infra/perf/go/config"
)
type statement int
const (
getOriginalValue statement = iota
createKeyMap
)
var statements = map[statement]string{
getOriginalValue: `
SELECT
original_value
FROM
ReverseKeyMap
WHERE
modified_value =$1 AND param_key=$2
`,
createKeyMap: `
INSERT INTO
ReverseKeyMap (modified_value, param_key, original_value)
VALUES
($1, $2, $3)
ON CONFLICT DO NOTHING
RETURNING
original_value
`,
}
var spannerStatements = map[statement]string{
getOriginalValue: `
SELECT
original_value
FROM
ReverseKeyMap
WHERE
modified_value =$1 AND param_key=$2
`,
createKeyMap: `
INSERT INTO
ReverseKeyMap (modified_value, param_key, original_value)
VALUES
($1, $2, $3)
ON CONFLICT (modified_value, param_key) DO NOTHING
RETURNING
original_value
`,
}
type ReverseKeyMapStoreImpl struct {
db pool.Pool
statements map[statement]string
}
// New returns a new *ReverseKeyMapStoreImpl.
func New(db pool.Pool, dbType config.DataStoreType) *ReverseKeyMapStoreImpl {
stmts := statements
if dbType == config.SpannerDataStoreType {
stmts = spannerStatements
}
return &ReverseKeyMapStoreImpl{
db: db,
statements: stmts,
}
}
// Use the updated value and the param key to retrieve the original value.
func (s *ReverseKeyMapStoreImpl) Get(ctx context.Context, modifiedValue string, key string) (string, error) {
if modifiedValue == "" || key == "" {
return "", skerr.Fmt("No value or key is given to get reverse key mapping. Key: %s, Value: %s", key, modifiedValue)
}
var originalValue string
if err := s.db.QueryRow(ctx, s.statements[getOriginalValue], modifiedValue, key).Scan(&originalValue); err != nil {
if err == pgx.ErrNoRows {
// no old value is found.
return "", nil
}
return "", skerr.Wrapf(err, "Failed to finish querying on old value for value: %s and key: %s", modifiedValue, key)
}
return originalValue, nil
}
// Create a new mapping from updated value and param key to the original value.
func (s *ReverseKeyMapStoreImpl) Create(ctx context.Context, modifiedValue string, key string, originalValue string) (string, error) {
if modifiedValue == "" || key == "" || originalValue == "" {
return "", skerr.Fmt("Value, key and old value are all required for reverse key mapping. Value: %s. Key: %s. Old value: %s", modifiedValue, key, originalValue)
}
returnedValue := ""
if err := s.db.QueryRow(ctx, s.statements[createKeyMap], modifiedValue, key, originalValue).Scan(&returnedValue); err != nil {
if err == pgx.ErrNoRows {
// No row is created. Collision.
return "", nil
}
return "", skerr.Wrapf(err, "Failed to create new reverse key map from value: %s, key: %s, to old value: %s", modifiedValue, key, originalValue)
}
return returnedValue, nil
}