-
Notifications
You must be signed in to change notification settings - Fork 137
Fix: ENR temp table creation fails for long table names #4846
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
base: BABEL_6_X_DEV
Are you sure you want to change the base?
Changes from all commits
798c7dd
f313cde
8872ab4
70c3a56
5380950
31cbe64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,8 +51,14 @@ | |
| #include "utils/float.h" | ||
| #include "utils/xid8.h" | ||
| #include "utils/xml.h" | ||
| #include "catalog/pg_class_d.h" | ||
| #include <math.h> | ||
|
|
||
| extern const char *ATTOPTION_BBF_ORIGINAL_TABLE_NAME; | ||
| extern char *get_value_by_name_from_array(ArrayType *array, const char *name); | ||
|
|
||
| static char *get_orig_temp_table_name(Oid relid); | ||
|
|
||
| #include "../src/babelfish_version.h" | ||
| #include "../src/datatype_info.h" | ||
| #include "../src/pltsql.h" | ||
|
|
@@ -1319,7 +1325,19 @@ get_enr_list(PG_FUNCTION_ARGS) | |
| MemSet(nulls, 0, sizeof(nulls)); | ||
|
|
||
| values[0] = ((EphemeralNamedRelationMetadata) lfirst(lc))->reliddesc; | ||
| values[1] = CStringGetTextDatum(((EphemeralNamedRelationMetadata) lfirst(lc))->name); | ||
| { | ||
| EphemeralNamedRelationMetadata md = (EphemeralNamedRelationMetadata) lfirst(lc); | ||
| const char *name = md->name; | ||
|
|
||
| /* Use original untruncated name from reloptions if available */ | ||
| if (md->enrtype == ENR_TSQL_TEMP) | ||
| { | ||
| char *orig = get_orig_temp_table_name(md->reliddesc); | ||
| if (orig) | ||
| name = orig; | ||
| } | ||
| values[1] = CStringGetTextDatum(name); | ||
| } | ||
|
|
||
| tuplestore_putvalues(tupstore, tupdesc, values, nulls); | ||
| } | ||
|
|
@@ -2798,6 +2816,33 @@ object_id(PG_FUNCTION_ARGS) | |
| * if there is no such object in specified database, if database id is not provided it will lookup in current database | ||
| * if user don't have right permission | ||
| */ | ||
| /* | ||
| * get_orig_temp_table_name - Get original untruncated name from reloptions. | ||
| * Returns palloc'd string or NULL if not found. | ||
| */ | ||
| static char * | ||
| get_orig_temp_table_name(Oid relid) | ||
| { | ||
| HeapTuple tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); | ||
| char *orig = NULL; | ||
|
|
||
| if (HeapTupleIsValid(tuple)) | ||
| { | ||
| Datum datum; | ||
| bool isnull; | ||
|
|
||
| datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull); | ||
| if (!isnull) | ||
| { | ||
| ArrayType *reloptions = DatumGetArrayTypeP(datum); | ||
| orig = get_value_by_name_from_array(reloptions, ATTOPTION_BBF_ORIGINAL_TABLE_NAME); | ||
| } | ||
| ReleaseSysCache(tuple); | ||
| } | ||
| /* orig remains valid after ReleaseSysCache - get_value_by_name_from_array palloc's a copy */ | ||
| return orig; | ||
| } | ||
|
|
||
| Datum | ||
| object_name(PG_FUNCTION_ARGS) | ||
| { | ||
|
|
@@ -2844,7 +2889,12 @@ object_name(PG_FUNCTION_ARGS) | |
| enr = GetENRTempTableWithOid(object_id, false); | ||
| if (enr != NULL && enr->md.enrtype == ENR_TSQL_TEMP) | ||
| { | ||
| PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text(enr->md.name)); | ||
| const char *name = enr->md.name; | ||
| char *orig = get_orig_temp_table_name(object_id); | ||
|
|
||
| if (orig) | ||
| name = orig; | ||
| PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text(name)); | ||
| } | ||
|
|
||
| /* search in pg_class by object_id */ | ||
|
|
@@ -2855,7 +2905,17 @@ object_name(PG_FUNCTION_ARGS) | |
| if (pg_class_aclcheck(object_id, user_id, ACL_SELECT) == ACLCHECK_OK) | ||
| { | ||
| Form_pg_class pg_class = (Form_pg_class) GETSTRUCT(tuple); | ||
| result_text = cstring_to_text(NameStr(pg_class->relname)); // make a copy before releasing syscache | ||
|
|
||
| if (pg_class->relpersistence == RELPERSISTENCE_TEMP && | ||
| NameStr(pg_class->relname)[0] == '#') | ||
|
Comment on lines
+2909
to
+2910
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: lets create a utility for this?
|
||
| { | ||
|
Comment on lines
+2909
to
+2911
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldn't we be handling this for all identifiers? are we doing this for now for temp tables only? |
||
| char *orig = get_orig_temp_table_name(object_id); | ||
| if (orig) | ||
| result_text = cstring_to_text(orig); | ||
| } | ||
|
|
||
| if (!result_text) | ||
| result_text = cstring_to_text(NameStr(pg_class->relname)); | ||
| schema_id = pg_class->relnamespace; | ||
| } | ||
| ReleaseSysCache(tuple); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3557,6 +3557,11 @@ tsql_IndexStmt: | |
| n->transformed = false; | ||
| n->if_not_exists = false; | ||
|
|
||
| if (n->idxname) | ||
| n->options = lappend(n->options, | ||
| makeDefElem("name_location", | ||
| (Node *) makeInteger(@7), @7)); | ||
|
|
||
|
Comment on lines
+3560
to
+3564
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is unconditional - we are populating the name_location field no matter what? should we add a |
||
| tsql_index_nulls_order(n->indexParams, n->accessMethod); | ||
| $$ = (Node *)n; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -175,7 +175,7 @@ extern PLtsql_function *find_cached_batch(int handle); | |
| extern void apply_post_compile_actions(PLtsql_function *func, InlineCodeBlockArgs *args); | ||
| Datum sp_prepare(PG_FUNCTION_ARGS); | ||
| Datum sp_unprepare(PG_FUNCTION_ARGS); | ||
| static List *transformSelectIntoStmt(CreateTableAsStmt *stmt); | ||
| static List *transformSelectIntoStmt(CreateTableAsStmt *stmt, const char *queryString); | ||
| static char *get_oid_type_string(int type_oid); | ||
| static int64 get_identity_into_args(Node *node); | ||
| extern char *construct_unique_index_name(char *index_name, char *relation_name); | ||
|
|
@@ -239,6 +239,7 @@ static TargetEntry* buildJsonEntry(int nestLevel, char* tableAlias, TargetEntry* | |
| static char *string_to_fixed_hash(const char *input); | ||
| static void processAutoColumns(Query *wrapperQuery, Query *origQuery, Alias *wrapperRteAlias, ForAutoContext *ctx, ForAutoMode mode); | ||
| extern const char *ATTOPTION_BBF_ORIGINAL_NAME; | ||
| extern const char *ATTOPTION_BBF_ORIGINAL_TABLE_NAME; | ||
| extern bool pltsql_ansi_defaults; | ||
| extern bool pltsql_quoted_identifier; | ||
| extern bool pltsql_concat_null_yields_null; | ||
|
|
@@ -5386,6 +5387,34 @@ bbf_ProcessUtility(PlannedStmt *pstmt, | |
| List *partition_schemes = stmt->excludeOpNames; | ||
|
|
||
| stmt->excludeOpNames = NIL; | ||
|
|
||
| /* | ||
| * For indexes on temp tables, extract the full original | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why just temp tables? why aren't we doing this for all indexes |
||
| * name from the query string using name_location stored | ||
| * by the parser. Remove name_location from options as | ||
| * it is for internal use only. | ||
| */ | ||
| { | ||
| ListCell *lc; | ||
| foreach(lc, stmt->options) | ||
| { | ||
| DefElem *opt = (DefElem *) lfirst(lc); | ||
| if (strcmp(opt->defname, "name_location") == 0) | ||
| { | ||
| if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP && | ||
| stmt->relation->relname[0] == '#' && original_name) | ||
| { | ||
| int loc = intVal(opt->arg); | ||
| char *full_name = extract_identifier(queryString + loc, NULL); | ||
| if (full_name) | ||
| original_name = full_name; | ||
| } | ||
| stmt->options = foreach_delete_current(stmt->options, lc); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (stmt->idxname && !stmt->isconstraint) | ||
| stmt->idxname = construct_unique_index_name(stmt->idxname, stmt->relation->relname); | ||
| /* | ||
|
|
@@ -8017,7 +8046,8 @@ get_identity_into_args(Node *node) | |
| } | ||
|
|
||
| static List * | ||
| transformSelectIntoStmt(CreateTableAsStmt *stmt) | ||
| transformSelectIntoStmt | ||
| (CreateTableAsStmt *stmt, const char *queryString) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we doing the same for other |
||
| { | ||
| List *result; | ||
| ListCell *elements; | ||
|
|
@@ -8258,6 +8288,31 @@ transformSelectIntoStmt(CreateTableAsStmt *stmt) | |
| } | ||
|
|
||
| result = lappend(result, stmt); | ||
|
|
||
| /* Store original name in reloption for SELECT INTO #temp with long names */ | ||
| if (into && into->rel && | ||
| into->rel->relpersistence == RELPERSISTENCE_TEMP && | ||
| into->rel->relname[0] == '#' && | ||
| into->rel->location >= 0 && queryString != NULL) | ||
| { | ||
| char *original_name = extract_identifier(queryString + into->rel->location, NULL); | ||
|
|
||
| if (original_name && strlen(original_name) >= NAMEDATALEN) | ||
| { | ||
| if (!altstmt) | ||
| { | ||
| altstmt = makeNode(AlterTableStmt); | ||
| altstmt->relation = into->rel; | ||
| altstmt->objtype = OBJECT_TABLE; | ||
| altstmt->cmds = NIL; | ||
| } | ||
| altstmt->cmds = lappend(altstmt->cmds, make_original_rel_name_cmd(original_name)); | ||
| pfree(original_name); | ||
| } | ||
| else if (original_name) | ||
| pfree(original_name); | ||
|
Comment on lines
+8310
to
+8313
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: unnecessary. pfree handles NULLs |
||
| } | ||
|
|
||
| if (altstmt && list_length(altstmt->cmds) > 0) | ||
| result = lappend(result, altstmt); | ||
|
|
||
|
|
@@ -8270,7 +8325,7 @@ void pltsql_bbfSelectIntoUtility(ParseState *pstate, PlannedStmt *pstmt, const c | |
|
|
||
| Node *parsetree = pstmt->utilityStmt; | ||
| List *stmts; | ||
| stmts = transformSelectIntoStmt((CreateTableAsStmt *)parsetree); | ||
| stmts = transformSelectIntoStmt((CreateTableAsStmt *)parsetree, queryString); | ||
| while (stmts != NIL) | ||
| { | ||
| Node *stmt = (Node *)linitial(stmts); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: can we instead make the utility itself handle all of this -
get_orig_temp_table_name(Enr)returns fullname or truncated name.