Skip to content

Commit 17b2f9e

Browse files
author
RUI LUO
committed
Map PG error 22P02 to SQL Server error 245 and add RPC error tests. Fix type conversion errors returning unmapped code 33557097 by mapping 22P02 to 245. Add 20 RPC error compatibility tests covering parameter errors, RAISERROR, runtime errors, nested errors, and edge cases.
1 parent cf8d2f7 commit 17b2f9e

16 files changed

+894
-328
lines changed

contrib/babelfishpg_tds/error_mapping.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,5 @@ XX000 ERRCODE_INTERNAL_ERROR "The table-valued parameter \"%s\" must be declared
187187
22008 ERRCODE_DATETIME_VALUE_OUT_OF_RANGE "Adding a value to a \'%s\' column caused an overflow." SQL_ERROR_517 16
188188
42P01 ERRCODE_UNDEFINED_TABLE "FOR JSON AUTO requires at least one table for generating JSON objects. Use FOR JSON PATH or add a FROM clause with a table name." SQL_ERROR_13600 16
189189
42P01 ERRCODE_FEATURE_NOT_SUPPORTED "sub-select and values for json auto are not currently supported." SQL_ERROR_13600 16
190+
22P02 ERRCODE_INVALID_TEXT_REPRESENTATION "invalid input syntax for type %s: \"%s\"" SQL_ERROR_245 16
190191

contrib/babelfishpg_tsql/src/catalog.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@ get_rpc_out_option(char *servername)
14331433
bool rpc_out_enabled = false; /* Default to disabled */
14341434

14351435
bbf_servers_def_rel = table_open(get_bbf_servers_def_oid(),
1436-
RowExclusiveLock);
1436+
AccessShareLock);
14371437

14381438
ScanKeyInit(&key,
14391439
Anum_bbf_servers_def_servername,
@@ -1455,7 +1455,7 @@ get_rpc_out_option(char *servername)
14551455
}
14561456

14571457
table_endscan(scan);
1458-
table_close(bbf_servers_def_rel, RowExclusiveLock);
1458+
table_close(bbf_servers_def_rel, AccessShareLock);
14591459
return rpc_out_enabled;
14601460
}
14611461

contrib/babelfishpg_tsql/src/linked_servers.c

Lines changed: 216 additions & 280 deletions
Large diffs are not rendered by default.

contrib/babelfishpg_tsql/src/linked_servers.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ typedef DBPROCESS * LinkedServerProcess;
102102
#define LINKED_SERVER_SET_PWD(login, password) DBSETLPWD(login, password)
103103
#define LINKED_SERVER_SET_APP(login) DBSETLAPP(login, "babelfish_linked_server")
104104
#define LINKED_SERVER_SET_VERSION(login) DBSETLVERSION(login, DBVERSION_74)
105+
#define LINKED_SERVER_SET_CHARSET(login, cs) DBSETLCHARSET(login, cs)
105106
#define LINKED_SERVER_SET_DBNAME(login, dbname) DBSETLDBNAME(login, dbname)
106107
#define LINKED_SERVER_SET_QUERY_TIMEOUT(timeout) dbsettime(timeout)
107108
#define LINKED_SERVER_SET_CONNECT_TIMEOUT(timeout) dbsetlogintime(timeout)
@@ -199,6 +200,7 @@ typedef int *LinkedServerProcess;
199200
#define LINKED_SERVER_SET_PWD(login, password) ((void)0)
200201
#define LINKED_SERVER_SET_APP(login) ((void)0)
201202
#define LINKED_SERVER_SET_VERSION(login) ((void)0)
203+
#define LINKED_SERVER_SET_CHARSET(login, cs) ((void)0)
202204
#define LINKED_SERVER_SET_DBNAME(login, dbname) ((void)0)
203205
#define LINKED_SERVER_SET_QUERY_TIMEOUT(timeout) ((void)0)
204206
#define LINKED_SERVER_SET_CONNECT_TIMEOUT(timeout) ((void)0)
@@ -294,11 +296,12 @@ extern void validate_procedure_select_only(const char *server_name,
294296
const char *schema_name,
295297
const char *procedure_name);
296298

297-
/* ANTLR-based SELECT-only validation */
299+
/* ANTLR-based SELECT-only validation (also extracts nested procedure calls) */
298300
extern void validate_remote_procedure_select_only_antlr(
299301
const char *definition,
300302
const char *server_name,
301303
const char *database_name,
302304
const char *schema_name,
303-
const char *procedure_name);
305+
const char *procedure_name,
306+
List **nested_procs_out);
304307
#endif

contrib/babelfishpg_tsql/src/pl_exec-2.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,6 @@ static int
874874
execute_remote_procedure_rpc(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt)
875875
{
876876
LinkedServerProcess lsproc = NULL;
877-
LinkedServerProcess validation_lsproc = NULL; /* Separate connection for validation to avoid TDS error 20019 */
878877
LINKED_SERVER_RETCODE erc;
879878
char *full_proc_name;
880879
int colcount = 0;
@@ -922,19 +921,17 @@ execute_remote_procedure_rpc(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt)
922921
*/
923922
LINKED_SERVER_DEBUG("SELECT-only validation: Validating procedure %s", full_proc_name);
924923

925-
/* Temporarily establish connection just for validation */
926-
linked_server_establish_connection(stmt->server_name, &validation_lsproc, false);
927-
928-
/* Call the ANTLR-based validation function from linked_servers.c */
924+
/*
925+
* Call the ANTLR-based validation function from linked_servers.c.
926+
* validate_procedure_select_only() manages its own connections internally —
927+
* each recursive level opens a connection, fetches the procedure definition,
928+
* validates it, closes the connection, then recurses into nested calls.
929+
*/
929930
validate_procedure_select_only(stmt->server_name,
930931
stmt->db_name ? stmt->db_name : get_cur_db_name(),
931932
stmt->schema_name ? stmt->schema_name : "dbo",
932933
stmt->proc_name);
933934

934-
/* Validation connection has been closed internally - mark as cleaned up */
935-
validation_lsproc = NULL;
936-
937-
938935
/*
939936
* PHASE 2: Open fresh TDS connection for RPC execution
940937
* Clean connection with no SQL query history
@@ -1301,15 +1298,7 @@ execute_remote_procedure_rpc(PLtsql_execstate *estate, PLtsql_stmt_exec *stmt)
13011298
param_data_buffers = NIL;
13021299
}
13031300

1304-
/* Clean up validation connection if error occurred during validation */
1305-
if (validation_lsproc)
1306-
{
1307-
LINKED_SERVER_CANCEL(validation_lsproc);
1308-
LINKED_SERVER_CLOSE(validation_lsproc);
1309-
validation_lsproc = NULL;
1310-
}
1311-
1312-
/* Clean up RPC connection if error occurred during RPC */
1301+
/* Clean up RPC connection */
13131302
if (lsproc)
13141303
{
13151304
LINKED_SERVER_CANCEL(lsproc);

contrib/babelfishpg_tsql/src/tsqlIface.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,15 @@ extern "C"
7272

7373
void report_antlr_error(ANTLR_result result);
7474

75+
#ifdef ENABLE_TDS_LIB
7576
void validate_remote_procedure_select_only_antlr(
7677
const char *definition,
7778
const char *server_name,
7879
const char *database_name,
7980
const char *schema_name,
80-
const char *procedure_name);
81+
const char *procedure_name,
82+
List **nested_procs_out);
83+
#endif
8184

8285
extern PLtsql_type *parse_datatype(const char *string, int location);
8386
extern bool is_tsql_text_ntext_or_image_datatype(Oid oid);
@@ -4295,15 +4298,21 @@ void report_antlr_error(ANTLR_result r)
42954298

42964299
#pragma GCC diagnostic pop
42974300

4301+
#ifdef ENABLE_TDS_LIB
42984302
void
42994303
validate_remote_procedure_select_only_antlr(
43004304
const char *definition,
43014305
const char *server_name,
43024306
const char *database_name,
43034307
const char *schema_name,
4304-
const char *procedure_name)
4308+
const char *procedure_name,
4309+
List **nested_procs_out)
43054310
{
43064311
try {
4312+
/* Initialize output parameter */
4313+
if (nested_procs_out)
4314+
*nested_procs_out = NIL;
4315+
43074316
// Parse T-SQL procedure body using ANTLR
43084317
MyInputStream stream(definition);
43094318
TSqlLexer lexer(&stream);
@@ -4328,6 +4337,27 @@ validate_remote_procedure_select_only_antlr(
43284337
validator.getStatementType()),
43294338
errhint("Only procedures containing SELECT statements are allowed for linked server execution")));
43304339
}
4340+
4341+
/*
4342+
* Convert C++ vector of nested procedure calls to PostgreSQL List*.
4343+
* This replaces the old extract_nested_procedure_calls() C string parser
4344+
* which was inferior because it could match EXEC inside string literals,
4345+
* comments, and was case-sensitive for keyword matching.
4346+
*/
4347+
if (nested_procs_out)
4348+
{
4349+
List *result = NIL;
4350+
for (const auto &np : validator.getNestedProcedures())
4351+
{
4352+
NestedProcedureInfo *info = (NestedProcedureInfo *) palloc(sizeof(NestedProcedureInfo));
4353+
info->server_name = np.server_name.empty() ? NULL : pstrdup(np.server_name.c_str());
4354+
info->database_name = np.database_name.empty() ? NULL : pstrdup(np.database_name.c_str());
4355+
info->schema_name = np.schema_name.empty() ? NULL : pstrdup(np.schema_name.c_str());
4356+
info->procedure_name = pstrdup(np.procedure_name.c_str());
4357+
result = lappend(result, info);
4358+
}
4359+
*nested_procs_out = result;
4360+
}
43314361
}
43324362
catch (PGErrorWrapperException &e) {
43334363
ereport(ERROR,
@@ -4341,6 +4371,7 @@ validate_remote_procedure_select_only_antlr(
43414371
server_name, database_name, schema_name, procedure_name)));
43424372
}
43434373
}
4374+
#endif /* ENABLE_TDS_LIB */
43444375

43454376
} // extern "C"
43464377

test/JDBC/expected/four-part-names-vu-verify.out

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,23 @@ SELECT * FROM bbf_fpn_server.invalid_db.dbo.fpn_table
8989
GO
9090
~~ERROR (Code: 33557097)~~
9191

92-
~~ERROR (Message: Remote server error: relation "invalid_db_dbo.fpn_table" does not exist)~~
92+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "invalid_db_dbo.fpn_table" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
9393

9494

9595
-- Invalid schema name (Should throw error)
9696
SELECT * FROM bbf_fpn_server.master.invalid_schema.fpn_table
9797
GO
9898
~~ERROR (Code: 33557097)~~
9999

100-
~~ERROR (Message: Remote server error: relation "invalid_schema.fpn_table" does not exist)~~
100+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "invalid_schema.fpn_table" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
101101

102102

103103
-- Invalid object name (Should throw error)
104104
SELECT * FROM bbf_fpn_server.master.dbo.invalid_fpn_table
105105
GO
106106
~~ERROR (Code: 33557097)~~
107107

108-
~~ERROR (Message: Remote server error: relation "dbo.invalid_fpn_table" does not exist)~~
108+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "dbo.invalid_fpn_table" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
109109

110110

111111
-- four part object is a procedure (Should throw error)
@@ -406,7 +406,7 @@ GO
406406
varchar#!#int#!#int#!#varbinary#!#datetime#!#tinyint#!#varchar#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#tinyint#!#nvarchar#!#bit#!#tinyint#!#nvarchar#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#uniqueidentifier#!#bit#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#uniqueidentifier#!#uniqueidentifier#!#int#!#smallint#!#nvarchar#!#int#!#nvarchar#!#bit#!#bit#!#smallint#!#tinyint#!#nvarchar#!#int#!#int#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#bit#!#int#!#nvarchar#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit
407407
~~ERROR (Code: 33557097)~~
408408

409-
~~ERROR (Message: Remote database not found: database "fpn_table') select * from openq8c86d09e50d4f800f5a8c351ddbe1b23" does not exist)~~
409+
~~ERROR (Message: TDS client library error: Msg #: 911, Msg state: 1, Msg: database "fpn_table') select * from openq8c86d09e50d4f800f5a8c351ddbe1b23" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
410410

411411

412412
select * from bbf_fpn_server."fpn_table'') select * from openquery(''bbf_fpn_server'', ''select * from master".sys.databases
@@ -415,7 +415,7 @@ GO
415415
varchar#!#int#!#int#!#varbinary#!#datetime#!#tinyint#!#varchar#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#tinyint#!#nvarchar#!#bit#!#tinyint#!#nvarchar#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit#!#uniqueidentifier#!#bit#!#tinyint#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#uniqueidentifier#!#uniqueidentifier#!#int#!#smallint#!#nvarchar#!#int#!#nvarchar#!#bit#!#bit#!#smallint#!#tinyint#!#nvarchar#!#int#!#int#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#bit#!#int#!#nvarchar#!#nvarchar#!#bit#!#bit#!#bit#!#bit#!#bit#!#bit
416416
~~ERROR (Code: 33557097)~~
417417

418-
~~ERROR (Message: Remote database not found: database "fpn_table') select * from openq8c86d09e50d4f800f5a8c351ddbe1b23" does not exist)~~
418+
~~ERROR (Message: TDS client library error: Msg #: 911, Msg state: 1, Msg: database "fpn_table') select * from openq8c86d09e50d4f800f5a8c351ddbe1b23" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
419419

420420

421421
-- SQL Injection in schema name
@@ -426,14 +426,14 @@ select * from bbf_fpn_server.master.[sys.tables'') select * from openquery(''bbf
426426
GO
427427
~~ERROR (Code: 33557097)~~
428428

429-
~~ERROR (Message: Remote server error: relation "master_sys.tables') select * fr465ba21cd478dfdbfd9c4c52873fc1ec.databases" does not exist)~~
429+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "master_sys.tables') select * fr465ba21cd478dfdbfd9c4c52873fc1ec.databases" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
430430

431431

432432
select * from bbf_fpn_server.master."sys.tables'') select * from openquery(''bbf_fpn_server'', ''select * from master.sys".databases
433433
GO
434434
~~ERROR (Code: 33557097)~~
435435

436-
~~ERROR (Message: Remote server error: relation "master_sys.tables') select * fr465ba21cd478dfdbfd9c4c52873fc1ec.databases" does not exist)~~
436+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "master_sys.tables') select * fr465ba21cd478dfdbfd9c4c52873fc1ec.databases" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
437437

438438

439439
-- SQL Injection in object name
@@ -444,14 +444,14 @@ select * from bbf_fpn_server.master.sys.[tables'') select * from openquery(''bbf
444444
GO
445445
~~ERROR (Code: 33557097)~~
446446

447-
~~ERROR (Message: Remote server error: relation "sys.tables') select * from openquer6fae7895a55a5b386bac33a1b4ac3386" does not exist)~~
447+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "sys.tables') select * from openquer6fae7895a55a5b386bac33a1b4ac3386" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
448448

449449

450450
select * from bbf_fpn_server.master.sys."tables'') select * from openquery(''bbf_fpn_server'', ''select * from master.sys.databases"
451451
GO
452452
~~ERROR (Code: 33557097)~~
453453

454-
~~ERROR (Message: Remote server error: relation "sys.tables') select * from openquer6fae7895a55a5b386bac33a1b4ac3386" does not exist)~~
454+
~~ERROR (Message: TDS client library error: Msg #: 33557097, Msg state: 1, Msg: relation "sys.tables') select * from openquer6fae7895a55a5b386bac33a1b4ac3386" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
455455

456456

457457
DROP TABLE fpn_table_insert_into

test/JDBC/expected/linked_servers-vu-verify.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ EXEC sp_testlinkedserver 'test_server'
318318
GO
319319
~~ERROR (Code: 33557097)~~
320320

321-
~~ERROR (Message: Remote database not found: database "maste" does not exist)~~
321+
~~ERROR (Message: TDS client library error: Msg #: 911, Msg state: 1, Msg: database "maste" does not exist, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
322322

323323

324324
EXEC sp_dropserver @server = 'test_server', @droplogins = 'droplogins'

test/JDBC/expected/openquery-vu-verify.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3515,7 +3515,7 @@ GO
35153515
int
35163516
~~ERROR (Code: 33557097)~~
35173517

3518-
~~ERROR (Message: Remote server error: division by zero)~~
3518+
~~ERROR (Message: TDS client library error: Msg #: 8134, Msg state: 1, Msg: division by zero, Server: BABELFISH, Process: , Line: 1, Level: 16)~~
35193519

35203520

35213521
-- Try executing a query that does not return a result set
@@ -3587,7 +3587,7 @@ GO
35873587
text
35883588
~~ERROR (Code: 33557097)~~
35893589

3590-
~~ERROR (Message: TDS client library error: DB #: 20047, DB Msg: DBPROCESS is dead or not enabled, OS #: 0, OS Msg: Success, Level: 9)~~
3590+
~~ERROR (Message: TDS client library error: DB #: 20003, DB Msg: server connection timed out, OS #: 0, OS Msg: Success, Level: 6)~~
35913591

35923592

35933593
-- Test connect timeout behaviour in OPENQUERY

test/JDBC/expected/remote-proc-exec-vu-cleanup.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,26 @@ DROP PROCEDURE IF EXISTS sp_Outer_MultipleInner;
5858
DROP PROCEDURE IF EXISTS sp_Outer_WithDynamicSQL;
5959
GO
6060

61+
-- Drop error message compatibility test procedures
62+
DROP PROCEDURE IF EXISTS sp_err_SingleInt;
63+
DROP PROCEDURE IF EXISTS sp_err_TwoParams;
64+
DROP PROCEDURE IF EXISTS sp_err_Raiserror16;
65+
DROP PROCEDURE IF EXISTS sp_err_Raiserror11;
66+
DROP PROCEDURE IF EXISTS sp_err_Raiserror10;
67+
DROP PROCEDURE IF EXISTS sp_err_RaiserrorCustomMsg;
68+
DROP PROCEDURE IF EXISTS sp_err_DivByZero;
69+
DROP PROCEDURE IF EXISTS sp_err_Overflow;
70+
DROP PROCEDURE IF EXISTS sp_err_ConversionError;
71+
DROP PROCEDURE IF EXISTS sp_err_StringTruncation;
72+
DROP PROCEDURE IF EXISTS sp_err_NullDeref;
73+
DROP PROCEDURE IF EXISTS sp_err_InnerRaiserror;
74+
DROP PROCEDURE IF EXISTS sp_err_NestedError;
75+
DROP PROCEDURE IF EXISTS sp_err_ReturnAfterError;
76+
DROP PROCEDURE IF EXISTS sp_err_MultipleErrors;
77+
DROP PROCEDURE IF EXISTS sp_err_PrintAndError;
78+
DROP PROCEDURE IF EXISTS sp_err_PrintOnly;
79+
GO
80+
6181
-- Drop linked server and login mapping
6282
EXEC sp_dropserver 'bbf_rpe_server', 'droplogins';
6383
GO

0 commit comments

Comments
 (0)