Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support type_id and type_name t-sql functions #1860

Merged
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2c380fb
support type_id and type_name functions
Sep 22, 2023
26c7fc3
Added files
Sep 22, 2023
f3b4ddd
Merge remote-tracking branch 'upstream/BABEL_3_X_DEV' into JIRA-BABEL…
Sep 26, 2023
421f040
CFix check failure
Sep 26, 2023
0aed36b
JDBC Test failure fix
Sep 27, 2023
e0fa56b
Empty Commit
Sep 27, 2023
db067fd
Merge branch 'babelfish-for-postgresql:BABEL_3_X_DEV' into JIRA-BABEL…
vaibhav412 Sep 27, 2023
7156bc3
Merge remote-tracking branch 'upstream/BABEL_3_X_DEV' into JIRA-BABEL…
Oct 3, 2023
303caec
Updated code
Oct 3, 2023
9c9e339
resolve merge conflict
Oct 18, 2023
935c2b9
added type_id and type name c functions
Oct 18, 2023
81a6a5e
Fixed Check failures
Oct 19, 2023
c8ef3c2
Merge remote-tracking branch 'upstream/BABEL_3_X_DEV' into JIRA-BABEL…
Oct 24, 2023
f34e983
Merge branch 'babelfish-for-postgresql:BABEL_3_X_DEV' into JIRA-BABEL…
vaibhav412 Oct 25, 2023
1fb4c93
splitted name change
Oct 25, 2023
67bb4e4
pg_mbstrlen
Oct 25, 2023
5601779
whitespace trailing
Oct 25, 2023
1b6bfba
pfree splitted
Oct 25, 2023
8503377
pointer and nargs changed
Oct 25, 2023
892c1aa
macro added
Oct 25, 2023
1a95b14
spacing
Oct 25, 2023
502803c
remove pfree
Oct 25, 2023
66f0a92
added pfree
Oct 25, 2023
ce34b1d
Added JDBC test cases
Oct 25, 2023
77f6670
Empty Commit
Oct 25, 2023
950b9a4
Remove some test cases
Oct 25, 2023
223e333
Remove some more tests
Oct 25, 2023
f6c1169
Added some JDBC test cases
Oct 26, 2023
f740ef9
Remove some test case
Oct 26, 2023
cba0ee9
added dbo.int test case
Oct 26, 2023
68d78cf
Added some test cases back
Oct 26, 2023
db672da
Added dbo.int test case
Oct 26, 2023
fd52203
Added dbo.varchar test case
Oct 26, 2023
29be00f
Added dbo.bigint test cases
Oct 26, 2023
2c71485
Update functions.c
vaibhav412 Oct 26, 2023
21a6931
Update babelfishpg_common.h
vaibhav412 Oct 26, 2023
bca62e3
Merge remote-tracking branch 'upstream/BABEL_3_X_DEV' into JIRA-BABEL…
Nov 6, 2023
5ac61cb
Resolved comments
Nov 6, 2023
00b89ec
Fix indentation
Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/babelfishpg_common/src/babelfishpg_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ get_common_utility_plugin(void)
common_utility_plugin_var.datetime2sqlvariant = &datetime2sqlvariant;
common_utility_plugin_var.tinyint2sqlvariant = &tinyint2sqlvariant;
common_utility_plugin_var.translate_pg_type_to_tsql = &translate_pg_type_to_tsql;
common_utility_plugin_var.get_tsql_datatype_oid = &get_tsql_datatype_oid;
common_utility_plugin_var.TdsGetPGbaseType = &TdsGetPGbaseType;
common_utility_plugin_var.TdsSetMetaData = &TdsSetMetaData;
common_utility_plugin_var.TdsPGbaseType = &TdsPGbaseType;
Expand Down
1 change: 1 addition & 0 deletions contrib/babelfishpg_common/src/babelfishpg_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ typedef struct common_utility_plugin
Datum (*datetime2sqlvariant) (PG_FUNCTION_ARGS);
Datum (*tinyint2sqlvariant) (PG_FUNCTION_ARGS);
Datum (*translate_pg_type_to_tsql) (PG_FUNCTION_ARGS);
Oid (*get_tsql_datatype_oid) (char *type_name);
void (*TdsGetPGbaseType) (uint8 variantBaseType, int *pgBaseType, int tempLen,
int *dataLen, int *variantHeaderLen);
void (*TdsSetMetaData) (bytea *result, int pgBaseType, int scale,
Expand Down
12 changes: 12 additions & 0 deletions contrib/babelfishpg_common/src/typecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,18 @@ translate_pg_type_to_tsql(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}

Oid
get_tsql_datatype_oid(char *type_name)
{
for (int i = 0; i < TOTAL_TYPECODE_COUNT; i++)
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
{
if (!strcmp(type_infos[i].tsql_typname, type_name)) {
return type_infos[i].oid;
}
}
return InvalidOid;
}

Oid
get_type_oid(int type_code)
{
Expand Down
1 change: 1 addition & 0 deletions contrib/babelfishpg_common/src/typecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ extern void handle_type_and_collation(struct Node *node, Oid typid, Oid collatio
extern bool check_target_type_is_sys_varchar(Oid funcid);
extern type_info_t get_tsql_type_info(uint8_t type_code);
extern Datum translate_pg_type_to_tsql(PG_FUNCTION_ARGS);
extern Oid get_tsql_datatype_oid(char *type_name);

/*
* TransMemoryContext Memory context is created to load hash table to
Expand Down
201 changes: 201 additions & 0 deletions contrib/babelfishpg_tsql/runtime/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

#define TSQL_STAT_GET_ACTIVITY_COLS 26
#define SP_DATATYPE_INFO_HELPER_COLS 23
#define TYPE_NAME_MAX_LENGTH 4000
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved

typedef enum
{
Expand Down Expand Up @@ -121,6 +122,8 @@ PG_FUNCTION_INFO_V1(checksum);
PG_FUNCTION_INFO_V1(has_dbaccess);
PG_FUNCTION_INFO_V1(object_id);
PG_FUNCTION_INFO_V1(object_name);
PG_FUNCTION_INFO_V1(type_id);
PG_FUNCTION_INFO_V1(type_name);
PG_FUNCTION_INFO_V1(sp_datatype_info_helper);
PG_FUNCTION_INFO_V1(language);
PG_FUNCTION_INFO_V1(identity_into_smallint);
Expand Down Expand Up @@ -1727,6 +1730,204 @@ object_name(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}

/*
* type_id
* Returns the object ID with type name as input.
* Returns NULL
* if input is NULL
* if there is no such type
* if user don't have right permission
* if any error occured
*/
Datum
type_id(PG_FUNCTION_ARGS)
{
char *db_name,
*schema_name,
*object_name;
char *physical_schema_name;
char *input;
char **splitted_object_name;
Oid schema_oid;
Oid user_id = GetUserId();
Oid result = InvalidOid;
int i;

if (PG_ARGISNULL(0))
PG_RETURN_NULL();
input = text_to_cstring(PG_GETARG_TEXT_PP(0));

/* strip trailing whitespace from input */
i = pg_mbstrlen(input);
while (i > 0 && isspace((unsigned char) input[i - 1]))
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
i--;
if(i < pg_mbstrlen(input))
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
input[i] = '\0';

/* length should be restricted to 4000 */
if (i > TYPE_NAME_MAX_LENGTH)
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
errmsg("input value is too long for object name")));

/* resolve the two part name */
splitted_object_name = split_object_name(input);
/* If three part name(db_name also included in input) then return null */
if(pg_mbstrlen(splitted_object_name[1]) != 0)
{
pfree(input);
for (int i = 0; i < 4; i++)
pfree(splitted_object_name[i]);
pfree(splitted_object_name);
PG_RETURN_NULL();
}
db_name = get_cur_db_name();
schema_name = splitted_object_name[2];
object_name = splitted_object_name[3];

/* downcase identifier if needed */
if (pltsql_case_insensitive_identifiers)
{
db_name = downcase_identifier(db_name, strlen(db_name), false, false);
schema_name = downcase_identifier(schema_name, strlen(schema_name), false, false);
object_name = downcase_identifier(object_name, strlen(object_name), false, false);
for (int i = 0; i < 4; i++)
pfree(splitted_object_name[i]);
}
else
pfree(splitted_object_name[0]);

pfree(input);
pfree(splitted_object_name);

/* truncate identifiers if needed */
truncate_tsql_identifier(db_name);
truncate_tsql_identifier(schema_name);
truncate_tsql_identifier(object_name);

if (!strcmp(schema_name, ""))
{
// To check if it is a system datatype, search in typecode list and it will give result oid, else if not it will return null.
result = (*common_utility_plugin_ptr->get_tsql_datatype_oid) (object_name);

// If null result, then it is not system datatype and now search with default schema in pg_type
if (!OidIsValid(result))
{
/* find the default schema for current user and get physical schema name */
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
const char *user = get_user_for_database(db_name);
const char *guest_role_name = get_guest_role_name(db_name);

if (!user)
{
pfree(db_name);
pfree(schema_name);
pfree(object_name);
PG_RETURN_NULL();
}
else if ((guest_role_name && strcmp(user, guest_role_name) == 0))
{
physical_schema_name = pstrdup(get_guest_schema_name(db_name));
}
else
{
pfree(schema_name);
schema_name = get_authid_user_ext_schema_name((const char *) db_name, user);
physical_schema_name = get_physical_schema_name(db_name, schema_name);
}
}
else
{
pfree(db_name);
pfree(schema_name);
pfree(object_name);
PG_RETURN_INT32(result);
}
}
else
{
physical_schema_name = get_physical_schema_name(db_name, schema_name);
}

/* get schema oid from physical schema name, it will return InvalidOid if user don't have lookup access */
schema_oid = get_namespace_oid(physical_schema_name, true);
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
pfree(db_name);
pfree(physical_schema_name);

if (!OidIsValid(schema_oid) || pg_namespace_aclcheck(schema_oid, user_id, ACL_USAGE) != ACLCHECK_OK)
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
{
pfree(schema_name);
pfree(object_name);
PG_RETURN_NULL();
}
// If schema is 'sys' or 'pg_catalog' then search in typecode list, else in pg_type.
if(!strcmp(schema_name, "sys") || !strcmp(schema_name, "pg_catalog"))
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
{
result = (*common_utility_plugin_ptr->get_tsql_datatype_oid) (object_name);
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
result = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
CStringGetDatum(object_name), ObjectIdGetDatum(schema_oid));
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
}
pfree(schema_name);
pfree(object_name);
if (OidIsValid(result) && pg_type_aclcheck(result, user_id, ACL_USAGE) == ACLCHECK_OK)
PG_RETURN_INT32(result);
else
PG_RETURN_NULL();
}

/*
* type_name
* returns the type name with type id as input
* Returns NULL
* if there is no such type
* if user don't have right permission
*/
Datum
type_name(PG_FUNCTION_ARGS)
{
Datum type_id = PG_GETARG_DATUM(0);
Datum tsql_typename;
HeapTuple tuple;
Oid user_id = GetUserId();
char *result = NULL;

LOCAL_FCINFO(fcinfo1, 1);

if (type_id < 0)
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
PG_RETURN_NULL();

InitFunctionCallInfoData(*fcinfo1, NULL, 1, InvalidOid, NULL, NULL);
fcinfo1->args[0].value = type_id;
fcinfo1->args[0].isnull = false;
// Search in typecode list, it will return type name if system datatype, else will return null.
tsql_typename = (*common_utility_plugin_ptr->translate_pg_type_to_tsql) (fcinfo1);
if (tsql_typename)
{
PG_RETURN_VARCHAR_P(tsql_typename);
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
// Search in pg_type catalog
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
if (HeapTupleIsValid(tuple))
{
if (pg_type_aclcheck(type_id, user_id, ACL_USAGE) == ACLCHECK_OK)
{
Form_pg_type pg_type = (Form_pg_type) GETSTRUCT(tuple);
result = NameStr(pg_type->typname);
}
ReleaseSysCache(tuple);
}
if (result)
{
PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text(result));
}
}
PG_RETURN_NULL();
}

Datum
has_dbaccess(PG_FUNCTION_ARGS)
{
Expand Down
10 changes: 10 additions & 0 deletions contrib/babelfishpg_tsql/sql/sys_functions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4387,6 +4387,16 @@ END;
$body$
LANGUAGE plpgsql IMMUTABLE;

CREATE OR REPLACE FUNCTION SYS.TYPE_NAME(IN type_id INT)
RETURNS SYS.NVARCHAR(128) AS
'babelfishpg_tsql', 'type_name'
LANGUAGE C STABLE;

CREATE OR REPLACE FUNCTION SYS.TYPE_ID(IN type_name SYS.NVARCHAR)
RETURNS INT AS
'babelfishpg_tsql', 'type_id'
LANGUAGE C STABLE;

CREATE OR REPLACE FUNCTION sys.DATETRUNC(IN datepart PG_CATALOG.TEXT, IN date ANYELEMENT) RETURNS ANYELEMENT AS
$body$
DECLARE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,16 @@ $$
LANGUAGE plpgsql IMMUTABLE
STRICT;

CREATE OR REPLACE FUNCTION SYS.TYPE_NAME(IN type_id INT)
vaibhav412 marked this conversation as resolved.
Show resolved Hide resolved
RETURNS SYS.NVARCHAR(128) AS
'babelfishpg_tsql', 'type_name'
LANGUAGE C STABLE;

CREATE OR REPLACE FUNCTION SYS.TYPE_ID(IN type_name SYS.NVARCHAR)
RETURNS INT AS
'babelfishpg_tsql', 'type_id'
LANGUAGE C STABLE;

CREATE OR REPLACE FUNCTION sys.SWITCHOFFSET(IN input_expr PG_CATALOG.TEXT,
IN tz_offset PG_CATALOG.TEXT)
RETURNS sys.datetimeoffset
Expand Down
27 changes: 27 additions & 0 deletions test/JDBC/expected/typeid-typename-dep-vu-cleanup.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
DROP VIEW typeid_typename_dep_vu_prepare_view1
GO

DROP PROC typeid_typename_dep_vu_prepare_proc1
GO

DROP VIEW typeid_typename_dep_vu_prepare_view2
GO

DROP PROC typeid_typename_dep_vu_prepare_proc2
GO

DROP TYPE typeid_typename_dep_vu_prepare_t1
GO

DROP TYPE typeid_typename_dep_vu_prepare_s1.typeid_typename_dep_vu_prepare_t1
GO

DROP SCHEMA typeid_typename_dep_vu_prepare_s1
GO

DROP USER typeid_typename_dep_vu_prepare_user1
GO

DROP LOGIN typeid_typename_dep_vu_prepare_log1
GO

31 changes: 31 additions & 0 deletions test/JDBC/expected/typeid-typename-dep-vu-prepare.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
CREATE TYPE typeid_typename_dep_vu_prepare_t1 FROM INT;
GO

CREATE SCHEMA typeid_typename_dep_vu_prepare_s1;
GO

CREATE TYPE typeid_typename_dep_vu_prepare_s1.typeid_typename_dep_vu_prepare_t1 FROM INT;
GO

CREATE VIEW typeid_typename_dep_vu_prepare_view1 AS
SELECT TYPE_NAME(TYPE_ID('typeid_typename_dep_vu_prepare_t1')) AS [1 Part Data Type Name], TYPE_NAME(TYPE_ID('typeid_typename_dep_vu_prepare_s1.typeid_typename_dep_vu_prepare_t1')) AS [2 Part Data Type Name];
GO

CREATE PROC typeid_typename_dep_vu_prepare_proc1 AS
SELECT TYPE_NAME(TYPE_ID('typeid_typename_dep_vu_prepare_t1')) AS [1 Part Data Type Name], TYPE_NAME(TYPE_ID('typeid_typename_dep_vu_prepare_s1.typeid_typename_dep_vu_prepare_t1')) AS [2 Part Data Type Name];
GO

CREATE VIEW typeid_typename_dep_vu_prepare_view2 AS
SELECT TYPE_NAME(TYPE_ID('datetime')) AS [TYPE_NAME];
GO

CREATE PROC typeid_typename_dep_vu_prepare_proc2 AS
SELECT TYPE_NAME(TYPE_ID('datetime')) AS [TYPE_NAME];
GO

CREATE LOGIN typeid_typename_dep_vu_prepare_log1 WITH PASSWORD = '12345678';
GO

CREATE USER typeid_typename_dep_vu_prepare_user1 FOR LOGIN typeid_typename_dep_vu_prepare_log1;
GO

Loading
Loading