From 3882511d750a9d92f91575e93599e3d5102dcbc1 Mon Sep 17 00:00:00 2001 From: "HOME5\\dmitr" Date: Mon, 27 Nov 2023 22:34:53 +0300 Subject: [PATCH] A proposal for fixing #7880 These changes force a server to return correct datatype for CAST(something as array datatype) - array type instead type of element. 1) Test of CAST(arrayColumn as ARRAY) SQL> set sqlda_display on; SQL> SELECT CAST(COL_I4 AS VARCHAR(128)[0:2]) FROM TEST_ARR1; INPUT message field count: 0 OUTPUT message field count: 1 01: sqltype: 540 ARRAY Nullable scale: 0 subtype: 0 len: 8 : name: CAST alias: CAST : table: owner: CAST ================= 111:0 Usage of UDFs with SCALAR_ARRAY-argument. These functions return different information about array: DIM, DTYPE, SUBTYPE, SCALE SQL> -- Bad column type: VARCHAR instead ARRAY SQL> -- FETCH returns incorrect data SQL> SELECT IBP_UDF__GET_ARR_DIM(CAST(COL_I4 AS VARCHAR(128)[0:2])) FROM TEST_ARR1; IBP_UDF__GET_ARR_DIM ==================== 1 SQL> SELECT IBP_UDF__GET_ARR_DESC_DTYPE(CAST(COL_I4 AS VARCHAR(128)[0:2])) FROM TEST_ARR1; IBP_UDF__GET_ARR_DESC_DTYPE =========================== 9 SQL> SELECT IBP_UDF__GET_ARR_DESC_LENGTH(CAST(COL_I4 AS VARCHAR(128)[0:2])) FROM TEST_ARR1; IBP_UDF__GET_ARR_DESC_LENGTH ============================ 4 SQL> SELECT IBP_UDF__ADTYPE__VCH64(CAST(COL_I4 AS VARCHAR(128)[0:2])) FROM TEST_ARR1; IBP_UDF__ADTYPE__VCH64 ====================== 3 SQL> SELECT IBP_UDF__ADTYPE__CH64(CAST(COL_I4 AS VARCHAR(128)[0:2])) FROM TEST_ARR1; IBP_UDF__ADTYPE__CH64 ===================== 1 SQL> -- Bad column type: INTEGER instead ARRAY SQL> -- FETCH returns conversion error from string "#x01#x01#x01#x00#x04# ....." SQL> SELECT IBP_UDF__GET_ARR_DIM(CAST(COL_I4 AS INTEGER[0:2])) FROM TEST_ARR1; IBP_UDF__GET_ARR_DIM ==================== 1 SQL> SELECT IBP_UDF__GET_ARR_DESC_DTYPE(CAST(COL_I4 AS INTEGER[0:2])) FROM TEST_ARR1; IBP_UDF__GET_ARR_DESC_DTYPE =========================== 9 SQL> SELECT IBP_UDF__ADTYPE__VCH64(CAST(COL_I4 AS INTEGER[0:2])) FROM TEST_ARR1; IBP_UDF__ADTYPE__VCH64 ====================== 3 SQL> SELECT IBP_UDF__ADTYPE__CH64(CAST(COL_I4 AS INTEGER[0:2])) FROM TEST_ARR1; IBP_UDF__ADTYPE__CH64 ===================== 1 2) TEST OF CAST(? AS array datatype) SQL> set sqlda_display on; SQL> SELECT CAST(? AS INTEGER[0:2]) FROM RDB$DATABASE; INPUT message field count: 1 01: sqltype: 540 ARRAY Nullable scale: 0 subtype: 0 len: 8 : name: alias: : table: owner: OUTPUT message field count: 1 01: sqltype: 540 ARRAY Nullable scale: 0 subtype: 0 len: 8 : name: CAST alias: CAST : table: owner: CAST ================= Statement failed, SQLSTATE = 07002 Dynamic SQL Error -SQLDA error -No SQLDA for input values provided --- src/dsql/DsqlCompilerScratch.cpp | 9 +++++++++ src/dsql/ddl_proto.h | 2 +- src/dsql/make.cpp | 15 ++++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/dsql/DsqlCompilerScratch.cpp b/src/dsql/DsqlCompilerScratch.cpp index 0fd80b587e9..cf9a5340644 100644 --- a/src/dsql/DsqlCompilerScratch.cpp +++ b/src/dsql/DsqlCompilerScratch.cpp @@ -139,6 +139,15 @@ void DsqlCompilerScratch::putDtype(const TypeClause* field, bool useSubType) return; } + if (field->dimensions != 0) + { + fb_assert(field->dimensions > 0); + fb_assert(blr_dtypes[dtype_array] == blr_quad); + appendUChar(blr_dtypes[dtype_array]); + appendUChar(0); + return; + } + switch (field->dtype) { case dtype_cstring: diff --git a/src/dsql/ddl_proto.h b/src/dsql/ddl_proto.h index 8b1fae8c2d4..31358b8d62a 100644 --- a/src/dsql/ddl_proto.h +++ b/src/dsql/ddl_proto.h @@ -54,7 +54,7 @@ const USHORT blr_dtypes[] = { blr_sql_time, // dtype_sql_time blr_timestamp, // dtype_timestamp blr_blob, // dtype_blob // ASF: CAST use blr_blob2 because blr_blob doesn't fit in UCHAR - blr_short, // dtype_array + blr_quad, // dtype_array blr_int64, // dtype_int64 0, // DB_KEY blr_bool, // dtype_boolean diff --git a/src/dsql/make.cpp b/src/dsql/make.cpp index dc1d7a6b9ef..c78716255d4 100644 --- a/src/dsql/make.cpp +++ b/src/dsql/make.cpp @@ -74,9 +74,18 @@ void DsqlDescMaker::fromElement(dsc* desc, const TypeClause* field) void DsqlDescMaker::fromField(dsc* desc, const TypeClause* field) { - composeDesc(desc, - field->dtype, field->scale, field->subType, field->length, - field->charSetId.value, field->collationId, field->flags & FLD_nullable); + if (field->dimensions != 0) + { + composeDesc(desc, + dtype_array, /*scale*/0, /*subType*/0, sizeof(ISC_QUAD), + /*charSetId*/0, /*collationId*/0, field->flags & FLD_nullable); + } + else + { + composeDesc(desc, + field->dtype, field->scale, field->subType, field->length, + field->charSetId.value, field->collationId, field->flags & FLD_nullable); + } } void DsqlDescMaker::fromList(DsqlCompilerScratch* scratch, dsc* desc,