Skip to content

Commit

Permalink
[sql] Add IsTableDoesNotExistErr method to Dialect (#608)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan-artie authored May 10, 2024
1 parent 7b16092 commit c789c26
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 46 deletions.
13 changes: 0 additions & 13 deletions clients/shared/errors.go

This file was deleted.

20 changes: 0 additions & 20 deletions clients/shared/errors_test.go

This file was deleted.

19 changes: 7 additions & 12 deletions clients/shared/table_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/artie-labs/transfer/lib/config/constants"
"github.com/artie-labs/transfer/lib/destination"
"github.com/artie-labs/transfer/lib/destination/types"
"github.com/artie-labs/transfer/lib/sql"
"github.com/artie-labs/transfer/lib/typing"
"github.com/artie-labs/transfer/lib/typing/columns"
)
Expand Down Expand Up @@ -60,17 +59,13 @@ func (g GetTableCfgArgs) GetTableConfig() (*types.DwhTableConfig, error) {

var tableMissing bool
if err != nil {
switch g.Dwh.Dialect().(type) {
case sql.SnowflakeDialect:
if SnowflakeTableDoesNotExistErr(err) {
// Swallow the error, make sure all the metadata is created
tableMissing = true
err = nil
} else {
return nil, fmt.Errorf("failed to query %T, err: %w, query: %v", g.Dwh, err, g.Query)
}
default:
return nil, fmt.Errorf("failed to query %T, err: %w", g.Dwh, err)
if g.Dwh.Dialect().IsTableDoesNotExistErr(err) {
// This branch is currently only used by Snowflake.
// Swallow the error, make sure all the metadata is created
tableMissing = true
err = nil
} else {
return nil, fmt.Errorf("failed to query %T, err: %w, query: %q", g.Dwh, err, g.Query)
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/sql/bigquery.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ func (BigQueryDialect) IsColumnAlreadyExistsErr(err error) bool {
return strings.Contains(err.Error(), "Column already exists")
}

func (BigQueryDialect) IsTableDoesNotExistErr(err error) bool {
return false
}

func (BigQueryDialect) BuildCreateTempTableQuery(fqTableName string, colSQLParts []string) string {
return fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s (%s) OPTIONS (expiration_timestamp = TIMESTAMP("%s"))`,
fqTableName, strings.Join(colSQLParts, ","), BQExpiresDate(time.Now().UTC().Add(constants.TemporaryTableTTL)))
Expand Down
1 change: 1 addition & 0 deletions lib/sql/dialect.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Dialect interface {
DataTypeForKind(kd typing.KindDetails, isPk bool) string
KindForDataType(_type string, stringPrecision string) (typing.KindDetails, error)
IsColumnAlreadyExistsErr(err error) bool
IsTableDoesNotExistErr(err error) bool
BuildCreateTempTableQuery(fqTableName string, colSQLParts []string) string
BuildProcessToastStructColExpression(colName string) string
}
4 changes: 4 additions & 0 deletions lib/sql/mssql.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ func (MSSQLDialect) IsColumnAlreadyExistsErr(err error) bool {
return false
}

func (MSSQLDialect) IsTableDoesNotExistErr(err error) bool {
return false
}

func (MSSQLDialect) BuildCreateTempTableQuery(fqTableName string, colSQLParts []string) string {
return fmt.Sprintf("CREATE TABLE %s (%s);", fqTableName, strings.Join(colSQLParts, ","))
}
Expand Down
4 changes: 4 additions & 0 deletions lib/sql/redshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ func (RedshiftDialect) IsColumnAlreadyExistsErr(err error) bool {
return strings.Contains(err.Error(), "already exists")
}

func (RedshiftDialect) IsTableDoesNotExistErr(err error) bool {
return false
}

func (RedshiftDialect) BuildCreateTempTableQuery(fqTableName string, colSQLParts []string) string {
return fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s);", fqTableName, strings.Join(colSQLParts, ","))
}
Expand Down
10 changes: 10 additions & 0 deletions lib/sql/snowflake.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ func (SnowflakeDialect) IsColumnAlreadyExistsErr(err error) bool {
return strings.Contains(err.Error(), "already exists")
}

// IsTableDoesNotExistErr will check if the resulting error message looks like this
// Table 'DATABASE.SCHEMA.TABLE' does not exist or not authorized. (resulting error message from DESC table)
func (SnowflakeDialect) IsTableDoesNotExistErr(err error) bool {
if err == nil {
return false
}

return strings.Contains(err.Error(), "does not exist or not authorized")
}

func (SnowflakeDialect) BuildCreateTempTableQuery(fqTableName string, colSQLParts []string) string {
// TEMPORARY Table syntax - https://docs.snowflake.com/en/sql-reference/sql/create-table
// PURGE syntax - https://docs.snowflake.com/en/sql-reference/sql/copy-into-table#purging-files-after-loading
Expand Down
15 changes: 14 additions & 1 deletion lib/sql/snowflake_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sql

import (
"fmt"
"testing"

"github.com/artie-labs/transfer/lib/typing"
Expand Down Expand Up @@ -132,7 +133,7 @@ func TestSnowflakeDialect_KindForDataType_Errors(t *testing.T) {
}
}

func TestSnowflakeTypeNoDataLoss(t *testing.T) {
func TestSnowflakeDialect_KindForDataType_NoDataLoss(t *testing.T) {
kindDetails := []typing.KindDetails{
typing.NewKindDetailsFromTemplate(typing.ETime, ext.DateTimeKindType),
typing.NewKindDetailsFromTemplate(typing.ETime, ext.TimeKindType),
Expand All @@ -148,3 +149,15 @@ func TestSnowflakeTypeNoDataLoss(t *testing.T) {
assert.Equal(t, kindDetail, kd)
}
}

func TestSnowflakeDialect_IsTableDoesNotExistErr(t *testing.T) {
errToExpectation := map[error]bool{
nil: false,
fmt.Errorf("Table 'DATABASE.SCHEMA.TABLE' does not exist or not authorized"): true,
fmt.Errorf("hi this is super random"): false,
}

for err, expectation := range errToExpectation {
assert.Equal(t, SnowflakeDialect{}.IsTableDoesNotExistErr(err), expectation, err)
}
}

0 comments on commit c789c26

Please sign in to comment.