@@ -3,6 +3,7 @@ package io.hasura.oracle
3
3
import io.hasura.ndc.common.ConnectorConfiguration
4
4
import io.hasura.ndc.common.NDCScalar
5
5
import io.hasura.ndc.ir.*
6
+ import io.hasura.ndc.ir.Type
6
7
import io.hasura.ndc.ir.Field.ColumnField
7
8
import io.hasura.ndc.ir.Field as IRField
8
9
import io.hasura.ndc.sqlgen.BaseQueryGenerator
@@ -19,23 +20,88 @@ object JsonQueryGenerator : BaseQueryGenerator() {
19
20
}
20
21
21
22
override fun queryRequestToSQL (request : QueryRequest ): Select <* > {
22
- return queryRequestToSQLInternal2(request)
23
+ return mkNativeQueryCTEs(request).select(
24
+ DSL .jsonArrayAgg(
25
+ buildJSONSelectionForQueryRequest(request)
26
+ ).returning(
27
+ SQLDataType .CLOB
28
+ )
29
+ )
23
30
}
24
31
25
- fun queryRequestToSQLInternal2 (
32
+ fun buildJSONSelectionForQueryRequest (
26
33
request : QueryRequest ,
27
34
parentTable : String? = null,
28
- parentRelationship : Relationship ? = null,
29
- ): SelectHavingStep <Record1 <JSON >> {
30
- val isRootQuery = parentRelationship == null
31
-
32
- return DSL .select(
33
- DSL .jsonObject(
34
- buildList {
35
- if (! request.query.fields.isNullOrEmpty()) {
36
- add(
37
- DSL .jsonEntry(
38
- " rows" ,
35
+ parentRelationship : Relationship ? = null
36
+ ): JSONObjectNullStep <* > {
37
+
38
+ val baseSelection = DSL .select(
39
+ DSL .table(DSL .name(request.collection)).asterisk()
40
+ ).from(
41
+ if (request.query.predicate == null ) {
42
+ DSL .table(DSL .name(request.collection))
43
+ } else {
44
+ val table = DSL .table(DSL .name(request.collection))
45
+ val requiredJoinTables = collectRequiredJoinTablesForWhereClause(
46
+ where = request.query.predicate!! ,
47
+ collectionRelationships = request.collection_relationships
48
+ )
49
+ requiredJoinTables.foldIndexed(table) { index, acc, relationship ->
50
+ val parentTable = if (index == 0 ) {
51
+ request.collection
52
+ } else {
53
+ requiredJoinTables.elementAt(index - 1 ).target_collection
54
+ }
55
+
56
+ val joinTable = DSL .table(DSL .name(relationship.target_collection))
57
+ acc.join(joinTable).on(
58
+ mkJoinWhereClause(
59
+ sourceTable = parentTable,
60
+ parentRelationship = relationship
61
+ )
62
+ )
63
+ }
64
+ }
65
+ ).apply {
66
+ if (request.query.predicate != null ) {
67
+ where(getWhereConditions(request))
68
+ }
69
+ if (parentRelationship != null ) {
70
+ where(
71
+ mkJoinWhereClause(
72
+ sourceTable = parentTable ? : error(" parentTable is null" ),
73
+ parentRelationship = parentRelationship
74
+ )
75
+ )
76
+ }
77
+ if (request.query.order_by != null ) {
78
+ orderBy(
79
+ translateIROrderByField(
80
+ orderBy = request.query.order_by,
81
+ currentCollection = getTableName(request.collection),
82
+ relationships = request.collection_relationships
83
+ )
84
+ )
85
+ }
86
+ if (request.query.limit != null ) {
87
+ limit(request.query.limit)
88
+ }
89
+ if (request.query.offset != null ) {
90
+ offset(request.query.offset)
91
+ }
92
+ }.apply {
93
+ addJoinsRequiredForOrderByFields(this , request)
94
+ }.asTable(
95
+ DSL .name(getTableName(request.collection))
96
+ )
97
+
98
+ return DSL .jsonObject(
99
+ buildList {
100
+ if (! request.query.fields.isNullOrEmpty()) {
101
+ add(
102
+ DSL .jsonEntry(
103
+ " rows" ,
104
+ DSL .select(
39
105
DSL .jsonArrayAgg(
40
106
DSL .jsonObject(
41
107
(request.query.fields ? : emptyMap()).map { (alias, field) ->
@@ -55,7 +121,7 @@ object JsonQueryGenerator : BaseQueryGenerator() {
55
121
request.collection_relationships[field.relationship]
56
122
? : error(" Relationship ${field.relationship} not found" )
57
123
58
- val subQuery = queryRequestToSQLInternal2 (
124
+ val subQuery = buildJSONSelectionForQueryRequest (
59
125
parentTable = request.collection,
60
126
parentRelationship = relationship,
61
127
request = QueryRequest (
@@ -70,9 +136,8 @@ object JsonQueryGenerator : BaseQueryGenerator() {
70
136
DSL .jsonEntry(
71
137
alias,
72
138
DSL .coalesce(
73
- DSL .select(
74
- subQuery.asField<Any >(alias)
75
- ), DSL .jsonObject(
139
+ DSL .select(subQuery),
140
+ DSL .jsonObject(
76
141
DSL .jsonEntry(
77
142
" rows" ,
78
143
DSL .jsonArray().returning(SQLDataType .CLOB )
@@ -84,109 +149,37 @@ object JsonQueryGenerator : BaseQueryGenerator() {
84
149
}
85
150
}
86
151
).returning(SQLDataType .CLOB )
87
- ).apply {
88
- if (request.query.order_by != null ) {
89
- orderBy(
90
- translateIROrderByField(
91
- orderBy = request.query.order_by,
92
- currentCollection = getTableName(request.collection),
93
- relationships = request.collection_relationships
94
- )
95
- )
96
- }
97
- }.returning(SQLDataType .CLOB )
152
+ ).returning(SQLDataType .CLOB )
153
+ ).from(
154
+ baseSelection
98
155
)
99
156
)
100
- }
101
- if (! request.query.aggregates.isNullOrEmpty()) {
102
- add(
103
- DSL .jsonEntry(
104
- " aggregates" ,
157
+ )
158
+ }
159
+ if (! request.query.aggregates.isNullOrEmpty()) {
160
+ add(
161
+ DSL .jsonEntry(
162
+ " aggregates" ,
163
+ DSL .select(
105
164
DSL .jsonObject(
106
165
(request.query.aggregates ? : emptyMap()).map { (alias, aggregate) ->
107
166
DSL .jsonEntry(
108
167
alias,
109
168
getAggregatejOOQFunction(aggregate)
110
169
)
111
170
}
112
- )
113
- )
114
- )
115
- }
116
- }
117
- ).returning(SQLDataType .CLOB ).let {
118
- when {
119
- isRootQuery -> DSL .jsonArrayAgg(it).returning(SQLDataType .CLOB )
120
- else -> it
121
- }
122
- }
123
- ).from(
124
- DSL .select(
125
- DSL .table(DSL .name(request.collection))
126
- .asterisk()
127
- ).from(
128
- run<Table <Record >> {
129
- val table = DSL .table(DSL .name(request.collection))
130
- if (request.query.predicate == null ) {
131
- table
132
- } else {
133
- val requiredJoinTables = collectRequiredJoinTablesForWhereClause(
134
- where = request.query.predicate!! ,
135
- collectionRelationships = request.collection_relationships
136
- )
137
-
138
- requiredJoinTables.foldIndexed(table) { index, acc, relationship ->
139
- val parentTable = if (index == 0 ) {
140
- request.collection
141
- } else {
142
- requiredJoinTables.elementAt(index - 1 ).target_collection
143
- }
144
-
145
- val joinTable = DSL .table(DSL .name(relationship.target_collection))
146
- acc.join(joinTable).on(
147
- mkJoinWhereClause(
148
- sourceTable = parentTable,
149
- parentRelationship = relationship
150
- )
171
+ ).returning(SQLDataType .CLOB )
172
+ ).from(
173
+ baseSelection
151
174
)
152
- }
153
- }
154
- }
155
- ).apply {
156
- if (request.query.predicate != null ) {
157
- where(getWhereConditions(request))
158
- }
159
- if (parentRelationship != null ) {
160
- where(
161
- mkJoinWhereClause(
162
- sourceTable = parentTable ? : error(" parentTable is null" ),
163
- parentRelationship = parentRelationship
164
- )
165
- )
166
- }
167
- if (request.query.order_by != null ) {
168
- orderBy(
169
- translateIROrderByField(
170
- orderBy = request.query.order_by,
171
- currentCollection = getTableName(request.collection),
172
- relationships = request.collection_relationships
173
175
)
174
176
)
175
177
}
176
- if (request.query.limit != null ) {
177
- limit(request.query.limit)
178
- }
179
- if (request.query.offset != null ) {
180
- offset(request.query.offset)
181
- }
182
- }.asTable(
183
- DSL .name(getTableName(request.collection))
184
- )
185
- ).groupBy(
186
- DSL .nullCondition()
187
- )
178
+ }
179
+ ).returning(SQLDataType .CLOB ) as JSONObjectNullStep <* >
188
180
}
189
-
181
+
182
+
190
183
fun collectRequiredJoinTablesForWhereClause (
191
184
where : Expression ,
192
185
collectionRelationships : Map <String , Relationship >,
@@ -223,13 +216,37 @@ object JsonQueryGenerator : BaseQueryGenerator() {
223
216
private fun columnTypeTojOOQType (collection : String , field : ColumnField ): org.jooq.DataType <out Any > {
224
217
val connectorConfig = ConnectorConfiguration .Loader .config
225
218
226
- val table = connectorConfig.tables.find { it.tableName == collection }
227
- ? : error(" Table $collection not found in connector configuration" )
219
+ val collectionIsTable = connectorConfig.tables.any { it.tableName == collection }
220
+ val collectionIsNativeQuery = connectorConfig.nativeQueries.containsKey(collection)
221
+
222
+ if (! collectionIsTable && ! collectionIsNativeQuery) {
223
+ error(" Collection $collection not found in connector configuration" )
224
+ }
225
+
226
+ val scalarType = when {
227
+ collectionIsTable -> {
228
+ val table = connectorConfig.tables.find { it.tableName == collection }
229
+ ? : error(" Table $collection not found in connector configuration" )
230
+
231
+ val column = table.columns.find { it.name == field.column }
232
+ ? : error(" Column ${field.column} not found in table $collection " )
228
233
229
- val column = table.columns.find { it.name == field.column }
230
- ? : error(" Column ${field.column} not found in table $collection " )
234
+ OracleJDBCSchemaGenerator .mapScalarType(column.type, column.numeric_scale)
235
+ }
236
+
237
+ collectionIsNativeQuery -> {
238
+ val nativeQuery = connectorConfig.nativeQueries[collection]
239
+ ? : error(" Native query $collection not found in connector configuration" )
240
+
241
+ val column = nativeQuery.columns[field.column]
242
+ ? : error(" Column ${field.column} not found in native query $collection " )
243
+
244
+ OracleJDBCSchemaGenerator .mapScalarType(Type .extractBaseType(column), null )
245
+ }
246
+
247
+ else -> error(" Collection $collection not found in connector configuration" )
248
+ }
231
249
232
- val scalarType = OracleJDBCSchemaGenerator .mapScalarType(column.type, column.numeric_scale)
233
250
return when (scalarType) {
234
251
NDCScalar .BOOLEAN -> SQLDataType .BOOLEAN
235
252
NDCScalar .INT -> SQLDataType .INTEGER
0 commit comments