1818package org .apache .kyuubi .server .trino .api
1919
2020import java .io .UnsupportedEncodingException
21- import java .net .{URLDecoder , URLEncoder }
21+ import java .net .{URI , URLDecoder , URLEncoder }
22+ import java .util
2223import javax .ws .rs .core .{HttpHeaders , Response }
2324
2425import scala .collection .JavaConverters ._
2526
27+ import io .trino .client .{ClientStandardTypes , ClientTypeSignature , Column , QueryError , QueryResults , StatementStats , Warning }
2628import io .trino .client .ProtocolHeaders .TRINO_HEADERS
27- import io .trino .client .QueryResults
29+ import org .apache .hive .service .rpc .thrift .{TGetResultSetMetadataResp , TRowSet , TTypeId }
30+
31+ import org .apache .kyuubi .operation .OperationStatus
2832
2933/**
3034 * The description and functionality of trino request
3135 * and response's context
3236 *
33- * @param user Specifies the session user, must be supplied with every query
34- * @param timeZone The timezone for query processing
37+ * @param user Specifies the session user, must be supplied with every query
38+ * @param timeZone The timezone for query processing
3539 * @param clientCapabilities Exclusive for trino server
36- * @param source This supplies the name of the software that submitted the query,
37- * e.g. `trino-jdbc` or `trino-cli` by default
38- * @param catalog The catalog context for query processing, will be set response
39- * @param schema The schema context for query processing
40- * @param language The language to use when processing the query and formatting results,
41- * formatted as a Java Locale string, e.g., en-US for US English
42- * @param traceToken Trace token for correlating requests across systems
43- * @param clientInfo Extra information about the client
44- * @param clientTags Client tags for selecting resource groups. Example: abc,xyz
45- * @param preparedStatement `preparedStatement` are kv pairs, where the names
46- * are names of previously prepared SQL statements,
47- * and the values are keys that identify the
48- * executable form of the named prepared statements
40+ * @param source This supplies the name of the software that submitted the query,
41+ * e.g. `trino-jdbc` or `trino-cli` by default
42+ * @param catalog The catalog context for query processing, will be set response
43+ * @param schema The schema context for query processing
44+ * @param language The language to use when processing the query and formatting results,
45+ * formatted as a Java Locale string, e.g., en-US for US English
46+ * @param traceToken Trace token for correlating requests across systems
47+ * @param clientInfo Extra information about the client
48+ * @param clientTags Client tags for selecting resource groups. Example: abc,xyz
49+ * @param preparedStatement `preparedStatement` are kv pairs, where the names
50+ * are names of previously prepared SQL statements,
51+ * and the values are keys that identify the
52+ * executable form of the named prepared statements
4953 */
5054case class TrinoContext (
5155 user : String ,
@@ -63,6 +67,11 @@ case class TrinoContext(
6367
6468object TrinoContext {
6569
70+ private val defaultWarning : util.List [Warning ] = new util.ArrayList [Warning ]()
71+ private val GENERIC_INTERNAL_ERROR_CODE = 65536
72+ private val GENERIC_INTERNAL_ERROR_NAME = " GENERIC_INTERNAL_ERROR_NAME"
73+ private val GENERIC_INTERNAL_ERROR_TYPE = " INTERNAL_ERROR"
74+
6675 def apply (headers : HttpHeaders ): TrinoContext = {
6776 apply(headers.getRequestHeaders.asScala.toMap.map {
6877 case (k, v) => (k, v.asScala.toList)
@@ -166,4 +175,196 @@ object TrinoContext {
166175 throw new AssertionError (e)
167176 }
168177
178+ def createQueryResults (
179+ queryId : String ,
180+ nextUri : URI ,
181+ queryHtmlUri : URI ,
182+ queryStatus : OperationStatus ,
183+ columns : Option [TGetResultSetMetadataResp ] = None ,
184+ data : Option [TRowSet ] = None ): QueryResults = {
185+
186+ val columnList = columns match {
187+ case Some (value) => convertTColumn(value)
188+ case None => null
189+ }
190+ val rowList = data match {
191+ case Some (value) => convertTRowSet(value)
192+ case None => null
193+ }
194+
195+ new QueryResults (
196+ queryId,
197+ queryHtmlUri,
198+ nextUri,
199+ nextUri,
200+ columnList,
201+ rowList,
202+ StatementStats .builder.setState(queryStatus.state.name()).setQueued(false )
203+ .setElapsedTimeMillis(0 ).setQueuedTimeMillis(0 ).build(),
204+ toQueryError(queryStatus),
205+ defaultWarning,
206+ null ,
207+ 0L )
208+ }
209+
210+ def convertTColumn (columns : TGetResultSetMetadataResp ): util.List [Column ] = {
211+ columns.getSchema.getColumns.asScala.map(c => {
212+ val tp = c.getTypeDesc.getTypes.get(0 ).getPrimitiveEntry.getType match {
213+ case TTypeId .BOOLEAN_TYPE => ClientStandardTypes .BOOLEAN
214+ case TTypeId .TINYINT_TYPE => ClientStandardTypes .TINYINT
215+ case TTypeId .SMALLINT_TYPE => ClientStandardTypes .SMALLINT
216+ case TTypeId .INT_TYPE => ClientStandardTypes .INTEGER
217+ case TTypeId .BIGINT_TYPE => ClientStandardTypes .BIGINT
218+ case TTypeId .FLOAT_TYPE => ClientStandardTypes .DOUBLE
219+ case TTypeId .DOUBLE_TYPE => ClientStandardTypes .DOUBLE
220+ case TTypeId .STRING_TYPE => ClientStandardTypes .VARCHAR
221+ case TTypeId .TIMESTAMP_TYPE => ClientStandardTypes .TIMESTAMP
222+ case TTypeId .BINARY_TYPE => ClientStandardTypes .VARBINARY
223+ case TTypeId .DECIMAL_TYPE => ClientStandardTypes .DECIMAL
224+ case TTypeId .DATE_TYPE => ClientStandardTypes .DATE
225+ case TTypeId .VARCHAR_TYPE => ClientStandardTypes .VARCHAR
226+ case TTypeId .CHAR_TYPE => ClientStandardTypes .CHAR
227+ case TTypeId .INTERVAL_YEAR_MONTH_TYPE => ClientStandardTypes .INTERVAL_YEAR_TO_MONTH
228+ case TTypeId .INTERVAL_DAY_TIME_TYPE => ClientStandardTypes .TIME_WITH_TIME_ZONE
229+ case TTypeId .TIMESTAMPLOCALTZ_TYPE => ClientStandardTypes .TIMESTAMP_WITH_TIME_ZONE
230+ case _ => ClientStandardTypes .VARCHAR
231+ }
232+ new Column (c.getColumnName, tp, new ClientTypeSignature (tp))
233+ }).toList.asJava
234+ }
235+
236+ def convertTRowSet (rowSet : TRowSet ): util.List [util.List [Object ]] = {
237+ val dataResult = new util.LinkedList [util.List [Object ]]
238+
239+ if (rowSet.getColumns == null ) {
240+ return rowSet.getRows.asScala
241+ .map(t => t.getColVals.asScala.map(v => v.getFieldValue.asInstanceOf [Object ]).asJava)
242+ .asJava
243+ }
244+
245+ rowSet.getColumns.asScala.foreach {
246+ case tColumn if tColumn.isSetBoolVal =>
247+ val nulls = util.BitSet .valueOf(tColumn.getBoolVal.getNulls)
248+ if (dataResult.isEmpty) {
249+ (1 to tColumn.getBoolVal.getValuesSize).foreach(_ =>
250+ dataResult.add(new util.LinkedList [Object ]()))
251+ }
252+
253+ tColumn.getBoolVal.getValues.asScala.zipWithIndex.foreach {
254+ case (_, rowIdx) if nulls.get(rowIdx) =>
255+ dataResult.get(rowIdx).add(null )
256+ case (v, rowIdx) =>
257+ dataResult.get(rowIdx).add(v)
258+ }
259+ case tColumn if tColumn.isSetByteVal =>
260+ val nulls = util.BitSet .valueOf(tColumn.getByteVal.getNulls)
261+ if (dataResult.isEmpty) {
262+ (1 to tColumn.getByteVal.getValuesSize).foreach(_ =>
263+ dataResult.add(new util.LinkedList [Object ]()))
264+ }
265+
266+ tColumn.getByteVal.getValues.asScala.zipWithIndex.foreach {
267+ case (_, rowIdx) if nulls.get(rowIdx) =>
268+ dataResult.get(rowIdx).add(null )
269+ case (v, rowIdx) =>
270+ dataResult.get(rowIdx).add(v)
271+ }
272+ case tColumn if tColumn.isSetI16Val =>
273+ val nulls = util.BitSet .valueOf(tColumn.getI16Val.getNulls)
274+ if (dataResult.isEmpty) {
275+ (1 to tColumn.getI16Val.getValuesSize).foreach(_ =>
276+ dataResult.add(new util.LinkedList [Object ]()))
277+ }
278+
279+ tColumn.getI16Val.getValues.asScala.zipWithIndex.foreach {
280+ case (_, rowIdx) if nulls.get(rowIdx) =>
281+ dataResult.get(rowIdx).add(null )
282+ case (v, rowIdx) =>
283+ dataResult.get(rowIdx).add(v)
284+ }
285+ case tColumn if tColumn.isSetI32Val =>
286+ val nulls = util.BitSet .valueOf(tColumn.getI32Val.getNulls)
287+ if (dataResult.isEmpty) {
288+ (1 to tColumn.getI32Val.getValuesSize).foreach(_ =>
289+ dataResult.add(new util.LinkedList [Object ]()))
290+ }
291+
292+ tColumn.getI32Val.getValues.asScala.zipWithIndex.foreach {
293+ case (_, rowIdx) if nulls.get(rowIdx) =>
294+ dataResult.get(rowIdx).add(null )
295+ case (v, rowIdx) =>
296+ dataResult.get(rowIdx).add(v)
297+ }
298+ case tColumn if tColumn.isSetI64Val =>
299+ val nulls = util.BitSet .valueOf(tColumn.getI64Val.getNulls)
300+ if (dataResult.isEmpty) {
301+ (1 to tColumn.getI64Val.getValuesSize).foreach(_ =>
302+ dataResult.add(new util.LinkedList [Object ]()))
303+ }
304+
305+ tColumn.getI64Val.getValues.asScala.zipWithIndex.foreach {
306+ case (_, rowIdx) if nulls.get(rowIdx) =>
307+ dataResult.get(rowIdx).add(null )
308+ case (v, rowIdx) =>
309+ dataResult.get(rowIdx).add(v)
310+ }
311+ case tColumn if tColumn.isSetDoubleVal =>
312+ val nulls = util.BitSet .valueOf(tColumn.getDoubleVal.getNulls)
313+ if (dataResult.isEmpty) {
314+ (1 to tColumn.getDoubleVal.getValuesSize).foreach(_ =>
315+ dataResult.add(new util.LinkedList [Object ]()))
316+ }
317+
318+ tColumn.getDoubleVal.getValues.asScala.zipWithIndex.foreach {
319+ case (_, rowIdx) if nulls.get(rowIdx) =>
320+ dataResult.get(rowIdx).add(null )
321+ case (v, rowIdx) =>
322+ dataResult.get(rowIdx).add(v)
323+ }
324+ case tColumn if tColumn.isSetBinaryVal =>
325+ val nulls = util.BitSet .valueOf(tColumn.getBinaryVal.getNulls)
326+ if (dataResult.isEmpty) {
327+ (1 to tColumn.getBinaryVal.getValuesSize).foreach(_ =>
328+ dataResult.add(new util.LinkedList [Object ]()))
329+ }
330+
331+ tColumn.getBinaryVal.getValues.asScala.zipWithIndex.foreach {
332+ case (_, rowIdx) if nulls.get(rowIdx) =>
333+ dataResult.get(rowIdx).add(null )
334+ case (v, rowIdx) =>
335+ dataResult.get(rowIdx).add(v)
336+ }
337+ case tColumn =>
338+ val nulls = util.BitSet .valueOf(tColumn.getStringVal.getNulls)
339+ if (dataResult.isEmpty) {
340+ (1 to tColumn.getStringVal.getValuesSize).foreach(_ =>
341+ dataResult.add(new util.LinkedList [Object ]()))
342+ }
343+
344+ tColumn.getStringVal.getValues.asScala.zipWithIndex.foreach {
345+ case (_, rowIdx) if nulls.get(rowIdx) =>
346+ dataResult.get(rowIdx).add(null )
347+ case (v, rowIdx) =>
348+ dataResult.get(rowIdx).add(v)
349+ }
350+ }
351+ dataResult
352+ }
353+
354+ def toQueryError (queryStatus : OperationStatus ): QueryError = {
355+ val exception = queryStatus.exception
356+ if (exception.isEmpty) {
357+ null
358+ } else {
359+ new QueryError (
360+ exception.get.getMessage,
361+ queryStatus.state.name(),
362+ GENERIC_INTERNAL_ERROR_CODE ,
363+ GENERIC_INTERNAL_ERROR_NAME ,
364+ GENERIC_INTERNAL_ERROR_TYPE ,
365+ null ,
366+ null )
367+ }
368+ }
369+
169370}
0 commit comments