mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-16 18:42:30 +03:00
39f5d04ba8
https://github.com/hasura/graphql-engine-mono/pull/2176 GitOrigin-RevId: 71f72704c3097ee05f3adca954b4c283701cf5e9
160 lines
4.7 KiB
Go
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
|
|
}
|