Skip to content

Commit 6556883

Browse files
authored
Merge pull request #39 from hasura/codedmart/type-rep
ndc-spec type representation
2 parents fe771ad + 67126aa commit 6556883

File tree

16 files changed

+1212
-315
lines changed

16 files changed

+1212
-315
lines changed

ndc-app/src/main/kotlin/io/hasura/ndc/app/services/JDBCSchemaGenerator.kt

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import io.hasura.ndc.app.interfaces.ISchemaGenerator
44
import io.hasura.ndc.common.ConnectorConfiguration
55
import io.hasura.ndc.common.*
66
import io.hasura.ndc.ir.*
7-
import jakarta.enterprise.context.ApplicationScoped
8-
import jakarta.enterprise.inject.Default
97

108
abstract class JDBCSchemaGenerator(
119
private val supportsMutations: Boolean = false
@@ -15,6 +13,7 @@ abstract class JDBCSchemaGenerator(
1513

1614
abstract fun mapScalarType(
1715
columnTypeStr: String,
16+
numericPrecision: Int?,
1817
numericScale: Int?
1918
): NDCScalar
2019

@@ -52,8 +51,8 @@ abstract class JDBCSchemaGenerator(
5251
description = it.description,
5352
arguments = emptyMap(),
5453
type = when (it.nullable) {
55-
true -> Type.Nullable(Type.Named(mapScalarType(it.type, it.numeric_scale).name))
56-
false -> Type.Named(mapScalarType(it.type, it.numeric_scale).name)
54+
true -> Type.Nullable(Type.Named(mapScalarType(it.type, it.numeric_precision, it.numeric_scale).name))
55+
false -> Type.Named(mapScalarType(it.type, it.numeric_precision, it.numeric_scale).name)
5756
}
5857
)
5958
}
@@ -87,7 +86,7 @@ abstract class JDBCSchemaGenerator(
8786
name = function.function_name,
8887
description = function.comment,
8988
arguments = emptyMap(),
90-
result_type = Type.Named(mapScalarType(function.data_type, null).name)
89+
result_type = Type.Named(mapScalarType(function.data_type, null, null).name)
9190
)
9291
}
9392

@@ -111,4 +110,30 @@ abstract class JDBCSchemaGenerator(
111110
override fun getSchema(config: ConnectorConfiguration): SchemaResponse {
112111
return buildSchema(config.tables, config.functions, config.nativeQueries)
113112
}
113+
114+
fun mapNumericPrecisionAndScaleToNDCScalar(
115+
precision: Int,
116+
scale: Int
117+
): NDCScalar {
118+
return when {
119+
scale != 0 -> when {
120+
// FLOAT32: Up to 7 digits (values from -3.4028235E+38 to 3.4028235E+38).
121+
precision <= 7 -> NDCScalar.FLOAT32
122+
// FLOAT64: Up to 15 digits (values from -1.7976931348623157E+308 to 1.7976931348623157E+308).
123+
precision <= 15 -> NDCScalar.FLOAT64
124+
// BIGDECIMAL: More than 15 digits.
125+
else -> NDCScalar.BIGDECIMAL
126+
}
127+
// INT8: Up to 3 digits (values from -128 to 127).
128+
precision <= 3 -> NDCScalar.INT8
129+
// INT16: Up to 5 digits (values from -32,768 to 32,767).
130+
precision <= 5 -> NDCScalar.INT16
131+
// INT32: Up to 10 digits (values from -2,147,483,648 to 2,147,483,647).
132+
precision <= 10 -> NDCScalar.INT32
133+
// INT64: Up to 19 digits (values from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807).
134+
precision <= 19 -> NDCScalar.INT64
135+
// BIGINTEGER: More than 19 digits.
136+
else -> NDCScalar.BIGINTEGER
137+
}
138+
}
114139
}

ndc-cli/src/main/kotlin/io/hasura/cli/MySQLConfigGenerator.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ object MySQLConfigGenerator : IConfigGenerator {
2525

2626
//language=MySQL
2727
val sql = """
28-
SELECT
28+
SELECT
2929
concat(tables.TABLE_SCHEMA, '.', tables.TABLE_NAME) AS TABLE_NAME,
3030
tables.TABLE_TYPE,
3131
tables.table_COMMENT as DESCRIPTION,
@@ -45,6 +45,7 @@ object MySQLConfigGenerator : IConfigGenerator {
4545
'name', columns.column_name,
4646
'description', columns.column_comment,
4747
'type', columns.data_type,
48+
'numeric_precision', columns.numeric_precision,
4849
'numeric_scale', columns.numeric_scale,
4950
'nullable', if (columns.is_nullable = 'yes', true, false),
5051
'auto_increment', if(columns.extra = 'auto_increment',true,false),

ndc-cli/src/main/kotlin/io/hasura/cli/OracleConfigGenerator.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ object OracleConfigGenerator : IConfigGenerator {
7272
'description' VALUE column_comments.COMMENTS,
7373
'type' VALUE columns.DATA_TYPE,
7474
'numeric_scale' VALUE columns.DATA_SCALE,
75+
'numeric_precision' VALUE columns.DATA_PRECISION,
7576
'nullable' VALUE case when columns.NULLABLE = 'Y' then 'true' else 'false' end,
7677
'auto_increment' VALUE case when columns.IDENTITY_COLUMN = 'YES' then 'true' else 'false' end
7778
)

ndc-cli/src/main/kotlin/io/hasura/cli/SnowflakeConfigGenerator.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ object SnowflakeConfigGenerator : IConfigGenerator {
6464
'name', columns.column_name,
6565
'description', columns.comment,
6666
'type', columns.data_type,
67+
'numeric_precision', columns.numeric_precision,
6768
'numeric_scale', columns.numeric_scale,
6869
'nullable', to_boolean(columns.is_nullable),
6970
'auto_increment', to_boolean(columns.is_identity)

ndc-cli/src/main/kotlin/io/hasura/cli/TrinoConfigGenerator.kt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@ object TrinoConfigGenerator : IConfigGenerator {
2929
WHERE table_schema = current_schema
3030
""".trimIndent()
3131

32+
33+
// Take a string of the format "decimal(20)" or "decimal(20,2)" and extract the numeric precision and scale
34+
fun extractNumericPrecisionAndScale(
35+
decimalString: String
36+
): Pair<Int, Int> {
37+
val (precision, scale) = decimalString
38+
.substringAfter("(")
39+
.substringBefore(")")
40+
.let {
41+
when {
42+
it.contains(",") -> it.split(",")
43+
else -> listOf(it, "0")
44+
}
45+
}
46+
.map { it.toInt() }
47+
return precision to scale
48+
}
49+
3250
// fetch every column, use jOOQ's fetchGroups to group them by table_name
3351
val tables = ctx.resultQuery(sql).fetchGroups("table_name").map { (tableName, rows) ->
3452
TableSchemaRow(
@@ -38,19 +56,26 @@ object TrinoConfigGenerator : IConfigGenerator {
3856
pks = emptyList(),
3957
fks = emptyMap(),
4058
columns = rows.map { row ->
59+
val dataType = row.get("data_type", String::class.java)
60+
val (numericPrecision, numericScale) = when {
61+
dataType.startsWith("decimal") -> extractNumericPrecisionAndScale(dataType)
62+
else -> null to null
63+
}
4164
ColumnSchemaRow(
4265
name = row.get("column_name", String::class.java),
4366
type = row.get("data_type", String::class.java),
4467
nullable = row.get("is_nullable", String::class.java) == "YES",
4568
auto_increment = false,
4669
is_primarykey = false,
4770
description = null,
48-
numeric_scale = null
71+
numeric_precision = numericPrecision,
72+
numeric_scale = numericScale
4973
)
5074
},
5175
)
5276
}
5377

78+
5479
return ConnectorConfiguration(
5580
jdbcUrl = jdbcUrl,
5681
jdbcProperties = emptyMap(),

ndc-connector-mysql/src/main/kotlin/io/hasura/mysql/JSONGenerator.kt

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import io.hasura.ndc.common.NDCScalar
55
import io.hasura.ndc.ir.*
66
import io.hasura.ndc.ir.Field.ColumnField
77
import io.hasura.ndc.ir.Field as IRField
8+
import io.hasura.ndc.ir.Type
89
import io.hasura.ndc.sqlgen.BaseQueryGenerator
910
import org.jooq.*
1011
import org.jooq.Field
@@ -123,12 +124,16 @@ object JsonQueryGenerator : BaseQueryGenerator() {
123124
(request.query.fields ?: emptyMap()).map { (alias, field) ->
124125
when (field) {
125126
is ColumnField -> {
127+
val columnField = DSL.field(DSL.name(field.column))
128+
val (columnType, ndcScalar) = columnTypeTojOOQType(
129+
MySQLJDBCSchemaGenerator::mapScalarType,
130+
request.collection,
131+
field
132+
)
133+
val castedField = castToSQLDataType(MYSQL, columnField, ndcScalar)
126134
DSL.jsonEntry(
127135
alias,
128-
DSL.field(
129-
DSL.name(field.column),
130-
// columnTypeTojOOQType(request.collection, field)
131-
)
136+
castedField
132137
)
133138
}
134139

@@ -230,31 +235,6 @@ object JsonQueryGenerator : BaseQueryGenerator() {
230235
}
231236
}
232237

233-
private fun ndcScalarTypeToSQLDataType(scalarType: NDCScalar): DataType<out Any> = when (scalarType) {
234-
NDCScalar.BOOLEAN -> SQLDataType.BOOLEAN
235-
NDCScalar.INT -> SQLDataType.INTEGER
236-
NDCScalar.FLOAT -> SQLDataType.FLOAT
237-
NDCScalar.STRING -> SQLDataType.CLOB
238-
NDCScalar.DATE -> SQLDataType.DATE
239-
NDCScalar.DATETIME -> SQLDataType.TIMESTAMP
240-
NDCScalar.DATETIME_WITH_TIMEZONE -> SQLDataType.TIMESTAMP
241-
NDCScalar.TIME -> SQLDataType.TIME
242-
NDCScalar.TIME_WITH_TIMEZONE -> SQLDataType.TIME
243-
}
244-
245-
private fun columnTypeTojOOQType(collection: String, field: ColumnField): org.jooq.DataType<out Any> {
246-
val connectorConfig = ConnectorConfiguration.Loader.config
247-
248-
val table = connectorConfig.tables.find { it.tableName == collection }
249-
?: error("Table $collection not found in connector configuration")
250-
251-
val column = table.columns.find { it.name == field.column }
252-
?: error("Column ${field.column} not found in table $collection")
253-
254-
val scalarType = MySQLJDBCSchemaGenerator.mapScalarType(column.type, column.numeric_scale)
255-
return ndcScalarTypeToSQLDataType(scalarType)
256-
}
257-
258238
private fun getAggregatejOOQFunction(aggregate: Aggregate) = when (aggregate) {
259239
is Aggregate.StarCount -> DSL.count()
260240
is Aggregate.SingleColumn -> {

0 commit comments

Comments
 (0)