From fdbd3fe799e8c9b138d3a8ed771e94d4adfba250 Mon Sep 17 00:00:00 2001 From: Shameem Ahmed <54461265+ahmed-shameem@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:56:54 +0530 Subject: [PATCH] Improve performance of sp_describe_undeclared_parameters (#1905) sp_describe_undeclared_parameters is slow. The issue is reported here: #1317. Initially, we used to create a query in C for every parameter passed as an argument to sp_describe_undeclared_parameters and then execute it. This was taking huge amount of time as it used JOINS among multiple views like sys.objects, sys.columns, sys.types T. In this commit, we have replaced the use of such views as much as possible with pg catalogs. This aids to the improvement in performance. Task: BABEL-3705 Signed-off-by: Shameem Ahmed --- contrib/babelfishpg_tsql/src/procedures.c | 377 +++++++++++++++------- 1 file changed, 267 insertions(+), 110 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/procedures.c b/contrib/babelfishpg_tsql/src/procedures.c index 099562d6589..32becc556e5 100644 --- a/contrib/babelfishpg_tsql/src/procedures.c +++ b/contrib/babelfishpg_tsql/src/procedures.c @@ -316,6 +316,9 @@ typedef struct UndeclaredParams /* The Oid of the table's schema */ Oid schemaoid; + + /* The Oid of the table */ + Oid reloid; } UndeclaredParams; static char * @@ -1114,6 +1117,7 @@ sp_describe_undeclared_parameters_internal(PG_FUNCTION_ARGS) strncpy(undeclaredparams->tablename, relation->relname, NAMEDATALEN); undeclaredparams->tablename[relname_len] = '\0'; undeclaredparams->schemaoid = RelationGetNamespace(r); + undeclaredparams->reloid = RelationGetRelid(r); undeclaredparams->targetattnums = (int *) palloc(sizeof(int) * list_length(target_attnums)); undeclaredparams->targetcolnames = (char **) palloc(sizeof(char *) * list_length(target_attnums)); @@ -1288,145 +1292,298 @@ sp_describe_undeclared_parameters_internal(PG_FUNCTION_ARGS) int col; int numresultcols = 24; char *tempq = - " SELECT " + "SELECT " "CAST( 0 AS INT ) " /* AS "parameter_ordinal" -- Need to get * correct ordinal number in code. */ ", CAST( NULL AS sysname ) " /* AS "name" -- Need to get correct * parameter name in code. */ - ", CASE " - "WHEN T2.name COLLATE sys.database_default = \'bigint\' THEN 127 " - "WHEN T2.name COLLATE sys.database_default = \'binary\' THEN 173 " - "WHEN T2.name COLLATE sys.database_default = \'bit\' THEN 104 " - "WHEN T2.name COLLATE sys.database_default = \'char\' THEN 175 " - "WHEN T2.name COLLATE sys.database_default = \'date\' THEN 40 " - "WHEN T2.name COLLATE sys.database_default = \'datetime\' THEN 61 " - "WHEN T2.name COLLATE sys.database_default = \'datetime2\' THEN 42 " - "WHEN T2.name COLLATE sys.database_default = \'datetimeoffset\' THEN 43 " - "WHEN T2.name COLLATE sys.database_default = \'decimal\' THEN 106 " - "WHEN T2.name COLLATE sys.database_default = \'float\' THEN 62 " - "WHEN T2.name COLLATE sys.database_default = \'image\' THEN 34 " - "WHEN T2.name COLLATE sys.database_default = \'int\' THEN 56 " - "WHEN T2.name COLLATE sys.database_default = \'money\' THEN 60 " - "WHEN T2.name COLLATE sys.database_default = \'nchar\' THEN 239 " - "WHEN T2.name COLLATE sys.database_default = \'ntext\' THEN 99 " - "WHEN T2.name COLLATE sys.database_default = \'numeric\' THEN 108 " - "WHEN T2.name COLLATE sys.database_default = \'nvarchar\' THEN 231 " - "WHEN T2.name COLLATE sys.database_default = \'real\' THEN 59 " - "WHEN T2.name COLLATE sys.database_default = \'smalldatetime\' THEN 58 " - "WHEN T2.name COLLATE sys.database_default = \'smallint\' THEN 52 " - "WHEN T2.name COLLATE sys.database_default = \'smallmoney\' THEN 122 " - "WHEN T2.name COLLATE sys.database_default = \'text\' THEN 35 " - "WHEN T2.name COLLATE sys.database_default = \'time\' THEN 41 " - "WHEN T2.name COLLATE sys.database_default = \'tinyint\' THEN 48 " - "WHEN T2.name COLLATE sys.database_default = \'uniqueidentifier\' THEN 36 " - "WHEN T2.name COLLATE sys.database_default = \'varbinary\' THEN 165 " - "WHEN T2.name COLLATE sys.database_default = \'varchar\' THEN 167 " - "WHEN T2.name COLLATE sys.database_default = \'xml\' THEN 241 " - "ELSE C.system_type_id " + ", CASE T2.name COLLATE sys.database_default " + "WHEN \'bigint\' THEN 127 " + "WHEN \'binary\' THEN 173 " + "WHEN \'bit\' THEN 104 " + "WHEN \'char\' THEN 175 " + "WHEN \'date\' THEN 40 " + "WHEN \'datetime\' THEN 61 " + "WHEN \'datetime2\' THEN 42 " + "WHEN \'datetimeoffset\' THEN 43 " + "WHEN \'decimal\' THEN 106 " + "WHEN \'float\' THEN 62 " + "WHEN \'image\' THEN 34 " + "WHEN \'int\' THEN 56 " + "WHEN \'money\' THEN 60 " + "WHEN \'nchar\' THEN 239 " + "WHEN \'ntext\' THEN 99 " + "WHEN \'numeric\' THEN 108 " + "WHEN \'nvarchar\' THEN 231 " + "WHEN \'real\' THEN 59 " + "WHEN \'smalldatetime\' THEN 58 " + "WHEN \'smallint\' THEN 52 " + "WHEN \'smallmoney\' THEN 122 " + "WHEN \'text\' THEN 35 " + "WHEN \'time\' THEN 41 " + "WHEN \'tinyint\' THEN 48 " + "WHEN \'uniqueidentifier\' THEN 36 " + "WHEN \'varbinary\' THEN 165 " + "WHEN \'varchar\' THEN 167 " + "WHEN \'xml\' THEN 241 " + "ELSE CASE " + "WHEN t.typbasetype = 0 THEN " + "CAST(a.atttypid AS int) " + "ELSE " + "CAST(t.typbasetype AS int) " + "END " "END " /* AS "suggested_system_type_id" */ - ", CASE " - "WHEN T2.name COLLATE sys.database_default = \'decimal\' THEN \'decimal(\' + CAST( C.precision AS sys.VARCHAR(10) ) + \',\' + CAST( C.scale AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'numeric\' THEN \'numeric(\' + CAST( C.precision AS sys.VARCHAR(10) ) + \',\' + CAST( C.scale AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'char\' THEN \'char(\' + CAST( C.max_length AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'nchar\' THEN \'nchar(\' + CAST( C.max_length/2 AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'binary\' THEN \'binary(\' + CAST( C.max_length AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'datetime2\' THEN \'datetime2(\' + CAST( C.scale AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'datetimeoffset\' THEN \'datetimeoffset(\' + CAST( C.scale AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'time\' THEN \'time(\' + CAST( C.scale AS sys.VARCHAR(10) ) + \')\' " - "WHEN T2.name COLLATE sys.database_default = \'varchar\' THEN " - "CASE WHEN C.max_length = -1 THEN \'varchar(max)\' " - "ELSE \'varchar(\' + CAST( C.max_length AS sys.VARCHAR(10) ) + \')\' " + ", CASE T2.name COLLATE sys.database_default " + "WHEN \'decimal\' THEN \'decimal(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_precision_helper(T2.name, a.atttypmod) " + "ELSE " + "sys.tsql_type_precision_helper(T2.name, t.typtypmod) " + "END AS sys.VARCHAR(10) ) + \',\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_scale_helper(T2.name, a.atttypmod, false) " + "ELSE " + "sys.tsql_type_scale_helper(T2.name, t.typtypmod, false) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'numeric\' THEN \'numeric(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_precision_helper(T2.name, a.atttypmod) " + "ELSE " + "sys.tsql_type_precision_helper(T2.name, t.typtypmod) " + "END AS sys.VARCHAR(10) ) + \',\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_scale_helper(T2.name, a.atttypmod, false) " + "ELSE " + "sys.tsql_type_scale_helper(T2.name, t.typtypmod, false) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'char\' THEN \'char(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'nchar\' THEN \'nchar(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END /2 AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'binary\' THEN \'binary(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'datetime2\' THEN \'datetime2(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_scale_helper(T2.name, a.atttypmod, false) " + "ELSE " + "sys.tsql_type_scale_helper(T2.name, t.typtypmod, false) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'datetimeoffset\' THEN \'datetimeoffset(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_scale_helper(T2.name, a.atttypmod, false) " + "ELSE " + "sys.tsql_type_scale_helper(T2.name, t.typtypmod, false) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'time\' THEN \'time(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_scale_helper(T2.name, a.atttypmod, false) " + "ELSE " + "sys.tsql_type_scale_helper(T2.name, t.typtypmod, false) " + "END AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'varchar\' THEN " + "CASE WHEN CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END = -1 THEN \'varchar(max)\' " + "ELSE \'varchar(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END AS sys.VARCHAR(10) ) + \')\' " "END " - "WHEN T2.name COLLATE sys.database_default = \'nvarchar\' THEN " - "CASE WHEN C.max_length = -1 THEN \'nvarchar(max)\' " - "ELSE \'nvarchar(\' + CAST( C.max_length/2 AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'nvarchar\' THEN " + "CASE WHEN CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END = -1 THEN \'nvarchar(max)\' " + "ELSE \'nvarchar(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END /2 AS sys.VARCHAR(10) ) + \')\' " "END " - "WHEN T2.name COLLATE sys.database_default = \'varbinary\' THEN " - "CASE WHEN C.max_length = -1 THEN \'varbinary(max)\' " - "ELSE \'varbinary(\' + CAST( C.max_length AS sys.VARCHAR(10) ) + \')\' " + "WHEN \'varbinary\' THEN " + "CASE WHEN CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END = -1 THEN \'varbinary(max)\' " + "ELSE \'varbinary(\' + CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END AS sys.VARCHAR(10) ) + \')\' " "END " "ELSE T2.name " "END " /* AS "suggested_system_type_name" */ - ", CASE " - "WHEN T2.name COLLATE sys.database_default IN (\'image\', \'ntext\',\'text\') THEN -1 " - "ELSE C.max_length " + ", CASE T2.name COLLATE sys.database_default " + "WHEN \'image\' THEN -1 " + "WHEN \'ntext\' THEN -1 " + "WHEN \'text\' THEN -1 " + "ELSE CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END " "END " /* AS "suggested_max_length" */ - ", C.precision " /* AS "suggested_precision" */ - ", C.scale " /* AS "suggested_scale" */ - ", CASE WHEN T.user_type_id = T.system_type_id THEN CAST( NULL AS INT ) ELSE T.user_type_id END " /* AS + ", CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_precision_helper(T2.name, a.atttypmod) " + "ELSE " + "sys.tsql_type_precision_helper(T2.name, t.typtypmod) " + "END " /* AS "suggested_precision" */ + ", CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_scale_helper(T2.name, a.atttypmod, false) " + "ELSE " + "sys.tsql_type_scale_helper(T2.name, t.typtypmod, false) " + "END " /* AS "suggested_scale" */ + ", CASE WHEN T2.user_type_id = T2.system_type_id THEN CAST( NULL AS INT ) ELSE T2.user_type_id END " /* AS * "suggested_user_type_id" */ - ", CASE WHEN T.user_type_id = T.system_type_id THEN CAST( NULL AS sysname) ELSE DB_NAME() END " /* AS + ", CASE WHEN T2.user_type_id = T2.system_type_id THEN CAST( NULL AS sysname) ELSE DB_NAME() END " /* AS * "suggested_user_type_database" */ - ", CASE WHEN T.user_type_id = T.system_type_id THEN CAST( NULL AS sysname) ELSE SCHEMA_NAME( T.schema_id ) END " /* AS + ", CASE WHEN T2.user_type_id = T2.system_type_id THEN CAST( NULL AS sysname) ELSE SCHEMA_NAME( T2.schema_id ) END " /* AS * "suggested_user_type_schema" */ - ", CASE WHEN T.user_type_id = T.system_type_id THEN CAST( NULL AS sysname) ELSE T.name END " /* AS + ", CASE WHEN T2.user_type_id = T2.system_type_id THEN CAST( NULL AS sysname) ELSE T2.name END " /* AS * "suggested_user_type_name" */ ", CAST( NULL AS NVARCHAR(4000) ) " /* AS * "suggested_assembly_qualified_type_name" */ - ", CASE " - "WHEN C.xml_collection_id = 0 THEN CAST( NULL AS INT ) " - "ELSE C.xml_collection_id " - "END " /* AS "suggested_xml_collection_id" */ + ", CAST( NULL AS INT ) " /* AS "suggested_xml_collection_id" */ ", CAST( NULL AS sysname ) " /* AS * "suggested_xml_collection_database" */ ", CAST( NULL AS sysname ) " /* AS * "suggested_xml_collection_schema" */ ", CAST( NULL AS sysname ) " /* AS "suggested_xml_collection_name" */ - ", C.is_xml_document " /* AS "suggested_is_xml_document" */ + ", CAST(0 AS sys.bit) " /* AS "suggested_is_xml_document" */ ", CAST( 0 AS BIT ) " /* AS "suggested_is_case_sensitive" */ ", CAST( 0 AS BIT ) " /* AS "suggested_is_fixed_length_clr_type" */ ", CAST( 1 AS BIT ) " /* AS "suggested_is_input" */ ", CAST( 0 AS BIT ) " /* AS "suggested_is_output" */ ", CAST( NULL AS sysname ) " /* AS "formal_parameter_name" */ - ", CASE " - "WHEN T2.name COLLATE sys.database_default IN (\'tinyint\', \'smallint\', \'int\', \'bigint\') THEN 38 " - "WHEN T2.name COLLATE sys.database_default IN (\'float\', \'real\') THEN 109 " - "WHEN T2.name COLLATE sys.database_default IN (\'smallmoney\', \'money\') THEN 110 " - "WHEN T2.name COLLATE sys.database_default IN (\'smalldatetime\', \'datetime\') THEN 111 " - "WHEN T2.name COLLATE sys.database_default = \'binary\' THEN 173 " - "WHEN T2.name COLLATE sys.database_default = \'bit\' THEN 104 " - "WHEN T2.name COLLATE sys.database_default = \'char\' THEN 175 " - "WHEN T2.name COLLATE sys.database_default = \'date\' THEN 40 " - "WHEN T2.name COLLATE sys.database_default = \'datetime2\' THEN 42 " - "WHEN T2.name COLLATE sys.database_default = \'datetimeoffset\' THEN 43 " - "WHEN T2.name COLLATE sys.database_default = \'decimal\' THEN 106 " - "WHEN T2.name COLLATE sys.database_default = \'image\' THEN 34 " - "WHEN T2.name COLLATE sys.database_default = \'nchar\' THEN 239 " - "WHEN T2.name COLLATE sys.database_default = \'ntext\' THEN 99 " - "WHEN T2.name COLLATE sys.database_default = \'numeric\' THEN 108 " - "WHEN T2.name COLLATE sys.database_default = \'nvarchar\' THEN 231 " - "WHEN T2.name COLLATE sys.database_default = \'text\' THEN 35 " - "WHEN T2.name COLLATE sys.database_default = \'time\' THEN 41 " - "WHEN T2.name COLLATE sys.database_default = \'uniqueidentifier\' THEN 36 " - "WHEN T2.name COLLATE sys.database_default= \'varbinary\' THEN 165 " - "WHEN T2.name COLLATE sys.database_default = \'varchar\' THEN 167 " - "WHEN T2.name COLLATE sys.database_default = \'xml\' THEN 241 " - "ELSE C.system_type_id " + ", CASE T2.name COLLATE sys.database_default " + "WHEN \'tinyint\' THEN 38 " + "WHEN \'smallint\' THEN 38 " + "WHEN \'int\' THEN 38 " + "WHEN \'bigint\' THEN 38 " + "WHEN \'float\' THEN 109 " + "WHEN \'real\' THEN 109 " + "WHEN \'smallmoney\' THEN 110 " + "WHEN \'money\' THEN 110 " + "WHEN \'smalldatetime\' THEN 111 " + "WHEN \'datetime\' THEN 111 " + "WHEN \'binary\' THEN 173 " + "WHEN \'bit\' THEN 104 " + "WHEN \'char\' THEN 175 " + "WHEN \'date\' THEN 40 " + "WHEN \'datetime2\' THEN 42 " + "WHEN \'datetimeoffset\' THEN 43 " + "WHEN \'decimal\' THEN 106 " + "WHEN \'image\' THEN 34 " + "WHEN \'nchar\' THEN 239 " + "WHEN \'ntext\' THEN 99 " + "WHEN \'numeric\' THEN 108 " + "WHEN \'nvarchar\' THEN 231 " + "WHEN \'text\' THEN 35 " + "WHEN \'time\' THEN 41 " + "WHEN \'uniqueidentifier\' THEN 36 " + "WHEN \'varbinary\' THEN 165 " + "WHEN \'varchar\' THEN 167 " + "WHEN \'xml\' THEN 241 " + "ELSE CASE " + "WHEN t.typbasetype = 0 THEN " + "CAST(a.atttypid AS int) " + "ELSE " + "CAST(t.typbasetype AS int) " + "END " "END " /* AS "suggested_tds_type_id" */ - ", CASE " - "WHEN T2.name COLLATE sys.database_default = \'nvarchar\' AND C.max_length = -1 THEN 65535 " - "WHEN T2.name COLLATE sys.database_default = \'varbinary\' AND C.max_length = -1 THEN 65535 " - "WHEN T2.name COLLATE sys.database_default = \'varchar\' AND C.max_length = -1 THEN 65535 " - "WHEN T2.name COLLATE sys.database_default IN (\'decimal\', \'numeric\') THEN 17 " - "WHEN T2.name COLLATE sys.database_default = \'xml\' THEN 8100 " - "WHEN T2.name COLLATE sys.database_default in (\'image\', \'text\') THEN 2147483647 " - "WHEN T2.name COLLATE sys.database_default = \'ntext\' THEN 2147483646 " - "ELSE CAST( C.max_length AS INT ) " + ", CASE T2.name COLLATE sys.database_default " + "WHEN \'nvarchar\' THEN " + "CASE WHEN CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END = -1 THEN 65535 " + "ELSE CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END " + "END " + "WHEN \'varbinary\' THEN " + "CASE WHEN CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END = -1 THEN 65535 " + "ELSE CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END " + "END " + "WHEN \'varchar\' THEN " + "CASE WHEN CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END = -1 THEN 65535 " + "ELSE CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END " + "END " + "WHEN \'decimal\' THEN 17 " + "WHEN \'numeric\' THEN 17 " + "WHEN \'xml\' THEN 8100 " + "WHEN \'image\' THEN 2147483647 " + "WHEN \'text\' THEN 2147483647 " + "WHEN \'ntext\' THEN 2147483646 " + "ELSE CAST( CASE " + "WHEN a.atttypmod != -1 THEN " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, a.atttypmod) " + "ELSE " + "sys.tsql_type_max_length_helper(T2.name, a.attlen, t.typtypmod) " + "END AS INT ) " "END " /* AS "suggested_tds_length" */ - "FROM sys.objects O, sys.columns C, sys.types T, sys.types T2 " - "WHERE O.object_id = C.object_id " - "AND C.user_type_id = T.user_type_id " - "AND C.name = \'%s\' COLLATE sys.database_default " /* -- INPUT column name */ - "AND T.system_type_id = T2.user_type_id " /* -- To get system dt - * name. */ - "AND O.name = \'%s\' COLLATE sys.database_default " /* -- INPUT table name */ - "AND O.schema_id = %d " /* -- INPUT schema Oid */ - "AND O.type = \'U\'"; /* -- User tables only for the time being */ - - char *query = psprintf(tempq, - undeclaredparams->targetcolnames[undeclaredparams->paramindexes[call_cntr]], - undeclaredparams->tablename, - undeclaredparams->schemaoid); + "FROM pg_attribute AS a " + "JOIN sys.types AS T2 ON a.atttypid = T2.user_type_id " + "JOIN pg_type AS t ON T2.user_type_id = t.oid " + ", sys.translate_pg_type_to_tsql(t.typbasetype) AS tsql_base_type_name " + "WHERE a.attrelid = %d " + "AND T2.system_type_id = T2.user_type_id " + "AND a.attname = \'%s\' COLLATE sys.database_default "; + + char *query = psprintf(tempq, + undeclaredparams->reloid, + undeclaredparams->targetcolnames[undeclaredparams->paramindexes[call_cntr]]); int rc = SPI_execute(query, true, 1);