From 41628f40c70663ca22a5c490ac2b86edcccad2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Wed, 21 Jun 2023 08:45:50 +0200 Subject: [PATCH] Add ColFits functions for other rdbms dialects --- .../adapters/rdbms/drivers/mssql/dialect.go | 49 ++++++++++++++++- .../rdbms/drivers/postgres/dialect.go | 55 ++++++++++++++++++- .../adapters/rdbms/drivers/sqlite/dialect.go | 49 ++++++++++++++++- 3 files changed, 150 insertions(+), 3 deletions(-) diff --git a/server/store/adapters/rdbms/drivers/mssql/dialect.go b/server/store/adapters/rdbms/drivers/mssql/dialect.go index d169ca879..cb212a3a5 100644 --- a/server/store/adapters/rdbms/drivers/mssql/dialect.go +++ b/server/store/adapters/rdbms/drivers/mssql/dialect.go @@ -230,7 +230,54 @@ func (mssqlDialect) AttributeToColumn(attr *dal.Attribute) (col *ddl.Column, err } func (mssqlDialect) ColumnFits(target, assert *ddl.Column) bool { - return false + targetType, targetName, targetMeta := ddl.ParseColumnTypes(target) + assertType, assertName, assertMeta := ddl.ParseColumnTypes(assert) + + // If everything matches up perfectly use that + if assertType == targetType { + return true + } + + // See if we can guess it + // [the type of the target column][what types fit the target col. type] + matches := map[string]map[string]bool{ + "bigint": { + "varchar": true, + }, + "datetime": { + "varchar": true, + }, + "time": { + "varchar": true, + }, + "date": { + "varchar": true, + }, + "decimal": { + "varchar": true, + }, + "varchar": {}, + "varbinary": {}, + "bit": {}, + "char": { + "varchar": true, + }, + } + + baseMatch := matches[assertName][targetName] + + // Special cases + switch { + case assertName == "varchar" && targetName == "varchar": + // Check varchar size + return baseMatch && assertMeta[0] <= targetMeta[0] + + case assertName == "decimal" && targetName == "decimal": + // Check decimal size and precision + return baseMatch && assertMeta[0] <= targetMeta[0] && assertMeta[1] <= targetMeta[1] + } + + return baseMatch } // @todo untested diff --git a/server/store/adapters/rdbms/drivers/postgres/dialect.go b/server/store/adapters/rdbms/drivers/postgres/dialect.go index 0290ffb6b..90d6d8dc9 100644 --- a/server/store/adapters/rdbms/drivers/postgres/dialect.go +++ b/server/store/adapters/rdbms/drivers/postgres/dialect.go @@ -215,7 +215,60 @@ func (postgresDialect) AttributeToColumn(attr *dal.Attribute) (col *ddl.Column, } func (postgresDialect) ColumnFits(target, assert *ddl.Column) bool { - return false + targetType, targetName, targetMeta := ddl.ParseColumnTypes(target) + assertType, assertName, assertMeta := ddl.ParseColumnTypes(assert) + + // If everything matches up perfectly use that + if assertType == targetType { + return true + } + + // See if we can guess it + // [the type of the target column][what types fit the target col. type] + matches := map[string]map[string]bool{ + "numeric": { + "text": true, + }, + "timestamp": { + "text": true, + + "timestamptz": true, + }, + "timestamptz": { + "text": true, + }, + "time": { + "text": true, + + "timetz": true, + }, + "timetz": { + "text": true, + }, + "date": { + "text": true, + }, + "text": {}, + "jsonb": {}, + "bytea": {}, + "boolean": { + "numeric": true, + }, + "uuid": { + "text": true, + }, + } + + baseMatch := matches[assertName][targetName] + + // Special cases + switch { + case assertName == "numeric" && targetName == "numeric": + // Check numeric size and precision + return baseMatch && assertMeta[0] <= targetMeta[0] && assertMeta[1] <= targetMeta[1] + } + + return baseMatch } func (d postgresDialect) ExprHandler(n *ql.ASTNode, args ...exp.Expression) (expr exp.Expression, err error) { diff --git a/server/store/adapters/rdbms/drivers/sqlite/dialect.go b/server/store/adapters/rdbms/drivers/sqlite/dialect.go index a08ac9614..9b0861359 100644 --- a/server/store/adapters/rdbms/drivers/sqlite/dialect.go +++ b/server/store/adapters/rdbms/drivers/sqlite/dialect.go @@ -219,7 +219,54 @@ func (sqliteDialect) AttributeToColumn(attr *dal.Attribute) (col *ddl.Column, er } func (sqliteDialect) ColumnFits(target, assert *ddl.Column) bool { - return false + targetType, targetName, targetMeta := ddl.ParseColumnTypes(target) + assertType, assertName, assertMeta := ddl.ParseColumnTypes(assert) + + // If everything matches up perfectly use that + if assertType == targetType { + return true + } + + // See if we can guess it + // [the type of the target column][what types fit the target col. type] + matches := map[string]map[string]bool{ + "bigint": { + "text": true, + "char": true, + }, + "timestamp": { + "text": true, + "char": true, + }, + "text": { + "char": true, + }, + "numeric": { + "text": true, + "char": true, + }, + "blob": {}, + "boolean": { + "text": true, + "char": true, + "bigint": true, + "numeric": true, + }, + "char": { + "text": true, + }, + } + + baseMatch := matches[assertName][targetName] + + // Special cases + switch { + case assertName == "char" && targetName == "char": + // Check char size + return baseMatch && assertMeta[0] <= targetMeta[0] + } + + return baseMatch } func (d sqliteDialect) ExprHandler(n *ql.ASTNode, args ...exp.Expression) (expr exp.Expression, err error) {