graphql-engine/cli/internal/statestore/migrations/hdbtable.go
Aravind K P 39f5d04ba8 cli: optimize state copy
https://github.com/hasura/graphql-engine-mono/pull/2176

GitOrigin-RevId: 71f72704c3097ee05f3adca954b4c283701cf5e9
2021-08-26 06:09:55 +00:00

160 lines
4.7 KiB
Go

package migrations
import (
"fmt"
"github.com/hasura/graphql-engine/cli/v2/internal/hasura"
"github.com/hasura/graphql-engine/cli/v2/internal/statestore"
"strconv"
"strings"
"github.com/hasura/graphql-engine/cli/v2/migrate/database"
)
const (
DefaultMigrationsTable = "schema_migrations"
DefaultSchema = "hdb_catalog"
)
// until version 1.4 migration state was stored a special table
// this struct will implement the methods required
type MigrationStateStoreHdbTable struct {
client hasura.PGSourceOps
schema, table string
}
func NewMigrationStateStoreHdbTable(client hasura.PGSourceOps, schema, table string) *MigrationStateStoreHdbTable {
return &MigrationStateStoreHdbTable{client, schema, table}
}
func (m *MigrationStateStoreHdbTable) InsertVersion(sourceName string, version int64) error {
query := hasura.PGRunSQLInput{
Source: sourceName,
SQL: `INSERT INTO ` + fmt.Sprintf("%s.%s", m.schema, m.table) + ` (version, dirty) VALUES (` + strconv.FormatInt(version, 10) + `, ` + fmt.Sprintf("%t", false) + `)`,
}
_, err := m.client.PGRunSQL(query)
if err != nil {
return err
}
return nil
}
func (m *MigrationStateStoreHdbTable) SetVersion(sourceName string, version int64, dirty bool) error {
if version >= 0 || (version == database.NilVersion && dirty) {
query := hasura.PGRunSQLInput{
Source: sourceName,
SQL: `INSERT INTO ` + fmt.Sprintf("%s.%s", m.schema, m.table) + ` (version, dirty) VALUES (` + strconv.FormatInt(version, 10) + `, ` + fmt.Sprintf("'%t'", dirty) + `)` + fmt.Sprintf(` ON CONFLICT(version) DO UPDATE SET dirty='%t'`, dirty),
}
_, err := m.client.PGRunSQL(query)
if err != nil {
return err
}
}
return nil
}
func (m *MigrationStateStoreHdbTable) RemoveVersion(sourceName string, version int64) error {
query := hasura.PGRunSQLInput{
Source: sourceName,
SQL: `DELETE FROM ` + fmt.Sprintf("%s.%s", m.schema, m.table) + ` WHERE version = ` + strconv.FormatInt(version, 10),
}
_, err := m.client.PGRunSQL(query)
if err != nil {
return err
}
return nil
}
func (m *MigrationStateStoreHdbTable) PrepareMigrationsStateStore(sourceName string) error {
// check if migration table exists
query := hasura.PGRunSQLInput{
Source: sourceName,
SQL: `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = '` + m.table + `' AND table_schema = '` + m.schema + `' LIMIT 1`,
}
runsqlResp, err := m.client.PGRunSQL(query)
if err != nil {
return err
}
if runsqlResp.ResultType != hasura.TuplesOK {
return fmt.Errorf("invalid result Type %s", runsqlResp.ResultType)
}
result := runsqlResp.Result
if result[1][0] != "0" {
return nil
}
// Now Create the table
query = hasura.PGRunSQLInput{
Source: sourceName,
SQL: `CREATE TABLE ` + fmt.Sprintf("%s.%s", m.schema, m.table) + ` (version bigint not null primary key, dirty boolean not null)`,
}
runsqlResp, err = m.client.PGRunSQL(query)
if err != nil {
return err
}
if runsqlResp.ResultType != hasura.CommandOK {
return fmt.Errorf("creating Version table failed %s", runsqlResp.ResultType)
}
return nil
}
func (m *MigrationStateStoreHdbTable) GetVersions(sourceName string) (map[uint64]bool, error) {
query := hasura.PGRunSQLInput{
SQL: `SELECT version, dirty FROM ` + fmt.Sprintf("%s.%s", m.schema, m.table),
Source: sourceName,
}
runsqlResp, err := m.client.PGRunSQL(query)
if err != nil {
return nil, err
}
if len(runsqlResp.Result) == 1 {
return nil, nil
}
var versions = map[uint64]bool{}
for index, val := range runsqlResp.Result {
if index == 0 {
continue
}
version, err := strconv.ParseInt(val[0], 10, 64)
if err != nil {
return nil, err
}
dirty, err := strconv.ParseBool(val[1])
if err != nil {
return nil, err
}
versions[uint64(version)] = dirty
// check if we have to mimic this
// m.hasuraDB.migrations.Append(database.MigrationVersion{Version: uint64(version), Dirty: dirty})
}
return versions, nil
}
// SetVersions is similar to SetVersion defined above. with the only difference, this is adapted to accept multiple versions
func (m *MigrationStateStoreHdbTable) SetVersions(sourceName string, versions []statestore.Version) error {
var insertSql []string
for _, v := range versions {
if v.Version >= 0 || (v.Version == database.NilVersion && v.Dirty) {
insertSql = append(insertSql, `INSERT INTO `+fmt.Sprintf("%s.%s", m.schema, m.table)+` (version, dirty) VALUES (`+strconv.FormatInt(v.Version, 10)+`, `+fmt.Sprintf("'%t'", v.Dirty)+`)`+fmt.Sprintf(` ON CONFLICT(version) DO UPDATE SET dirty='%t'`, v.Dirty))
}
}
if len(insertSql) > 0 {
query := hasura.PGRunSQLInput{
Source: sourceName,
SQL: strings.Join(insertSql, ";"),
}
_, err := m.client.PGRunSQL(query)
if err != nil {
return err
}
}
return nil
}