Skip to content

Commit

Permalink
Fix Join Re-Writing for Delete Queries using Output (#1902)
Browse files Browse the repository at this point in the history
BBF has operators for BIT=INT and BIT=BIT. It must chose to cast the
varchar to BIT or to INT. Currently it picks INT as it has a higher
precedence, but the cast fails. We should prioritize same-typed
operators when picking which to use.

Task: BABEL-4199
Signed-off-by: Walt Boettge <[email protected]>
  • Loading branch information
wboettge authored Oct 27, 2023
1 parent acd6756 commit de275ea
Show file tree
Hide file tree
Showing 10 changed files with 671 additions and 142 deletions.
21 changes: 18 additions & 3 deletions contrib/babelfishpg_tsql/src/backend_parser/gram-tsql-epilogue.y.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,20 @@ tsql_update_delete_stmt_from_clause_alias_helper(RangeVar *relation, RangeVar *r
}
}

/*
* Resets the state of two global vars used for UPDATE and DELETE queries
*
* In some cases, an erroring UPDATE query can exit without resetting these
* globals. This function is called before UPDATE and DELETE statements that
* use these globals to ensure that they are cleared.
*/
static void
tsql_reset_update_delete_globals()
{
output_update_transformation = false;
update_delete_target_alias = NULL;
}

static void
tsql_update_delete_stmt_from_clause_alias(RangeVar *relation, List *from_clause)
{
Expand Down Expand Up @@ -1074,6 +1088,8 @@ tsql_delete_output_into_cte_transformation(WithClause *opt_with_clause, Node *op
snprintf(ctename, NAMEDATALEN, "internal_output_cte##sys_gen##%p", (void *) i);
internal_ctename = pstrdup(ctename);

tsql_reset_update_delete_globals();

/* PreparableStmt inside CTE */
d->relation = relation_expr_opt_alias;
tsql_update_delete_stmt_from_clause_alias(d->relation, from_clause);
Expand All @@ -1082,15 +1098,12 @@ tsql_delete_output_into_cte_transformation(WithClause *opt_with_clause, Node *op
d = (DeleteStmt *) tsql_update_delete_stmt_with_join(
(Node *) d, from_clause, where_or_current_clause, opt_top_clause,
relation_expr_opt_alias, yyscanner);
output_update_transformation = true;
}
else
{
d->usingClause = from_clause;
d->whereClause = where_or_current_clause;
d->limitCount = opt_top_clause;
if (from_clause != NULL && (IsA(linitial(from_clause), RangeSubselect) || IsA(linitial(from_clause), RangeVar)))
output_update_transformation = true;
}
d->returningList = get_transformed_output_list(tsql_output_clause);
d->withClause = opt_with_clause;
Expand Down Expand Up @@ -1244,6 +1257,8 @@ tsql_update_output_into_cte_transformation(WithClause *opt_with_clause, Node *op
snprintf(ctename, NAMEDATALEN, "internal_output_cte##sys_gen##%p", (void *) i);
internal_ctename = pstrdup(ctename);

tsql_reset_update_delete_globals();

/* PreparableStmt inside CTE */
u->relation = relation_expr_opt_alias;
tsql_update_delete_stmt_from_clause_alias(u->relation, from_clause);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ char *construct_unique_index_name(char *index_name, char *relation_name);

static Node *tsql_update_delete_stmt_with_join(Node *n, List *from_clause, Node *where_clause, Node *top_clause, RangeVar *relation,
core_yyscan_t yyscanner);
static void tsql_reset_update_delete_globals(void);
static void tsql_update_delete_stmt_from_clause_alias(RangeVar *relation, List *from_clause);
static Node *tsql_insert_output_into_cte_transformation(WithClause *opt_with_clause, Node *opt_top_clause, RangeVar *insert_target,
List *insert_column_list, List *tsql_output_clause, RangeVar *output_target, List *tsql_output_into_target_columns,
Expand Down
149 changes: 13 additions & 136 deletions contrib/babelfishpg_tsql/src/backend_parser/gram-tsql-rule.y
Original file line number Diff line number Diff line change
Expand Up @@ -1284,112 +1284,36 @@ DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias
}
;

tsql_UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
n->relation = $3;
n->targetList = $5;
n->fromClause = $6;
n->whereClause = $7;
n->returningList = $8;
n->withClause = $1;
$$ = (Node *)n;
}
| opt_with_clause UPDATE relation_expr_opt_alias
tsql_table_hint_expr
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
n->relation = $3;
n->targetList = $6;
n->fromClause = $7;
n->whereClause = $8;
n->returningList = $9;
n->withClause = $1;
$$ = (Node *)n;
}
| opt_with_clause UPDATE tsql_top_clause relation_expr_opt_alias
tsql_UpdateStmt: opt_with_clause UPDATE opt_top_clause relation_expr_opt_alias
tsql_opt_table_hint_expr
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
n->relation = $4;
tsql_reset_update_delete_globals();
n->withClause = $1;
n->limitCount = $3;
n->relation = $4;
n->targetList = $7;
n->fromClause = $8;
n->whereClause = $9;
n->returningList = $10;
n->withClause = $1;
$$ = (Node *)n;
}
/* OUTPUT syntax */
| opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
tsql_output_clause
from_clause
where_or_current_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
n->relation = $3;
tsql_update_delete_stmt_from_clause_alias(n->relation, $7);
n->targetList = $5;
if ($7 != NULL && IsA(linitial($7), JoinExpr))
{
n = (UpdateStmt*)tsql_update_delete_stmt_with_join(
(Node*)n, $7, $8, NULL, $3,
yyscanner);

}
else
{
n->fromClause = $7;
n->whereClause = $8;
}
tsql_check_update_output_transformation($6);
n->returningList = $6;
n->withClause = $1;
$$ = (Node *)n;
}
| opt_with_clause UPDATE relation_expr_opt_alias
tsql_table_hint_expr
SET set_clause_list
tsql_output_clause
from_clause
where_or_current_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
n->relation = $3;
tsql_update_delete_stmt_from_clause_alias(n->relation,
$8);
n->targetList = $6;
n->fromClause = $8;
n->whereClause = $9;
tsql_check_update_output_transformation($7);
n->returningList = $7;
n->withClause = $1;
$$ = (Node *)n;
}
| opt_with_clause UPDATE tsql_top_clause relation_expr_opt_alias
| opt_with_clause UPDATE opt_top_clause relation_expr_opt_alias
tsql_opt_table_hint_expr
SET set_clause_list
tsql_output_clause
from_clause
where_or_current_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
tsql_reset_update_delete_globals();
n->relation = $4;
tsql_update_delete_stmt_from_clause_alias(n->relation,
$8);
tsql_update_delete_stmt_from_clause_alias(n->relation, $9);
n->targetList = $7;
if ($9 != NULL && IsA(linitial($9), JoinExpr))
{
Expand All @@ -1409,26 +1333,7 @@ tsql_UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
$$ = (Node *)n;
}
/* OUTPUT INTO syntax with OUTPUT target column list */
| opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
tsql_output_clause INTO insert_target tsql_output_into_target_columns
from_clause
where_or_current_clause
{
$$ = tsql_update_output_into_cte_transformation($1, NULL, $3, $5, $6, $8,
$9, $10, $11, yyscanner);
}
| opt_with_clause UPDATE relation_expr_opt_alias
tsql_table_hint_expr
SET set_clause_list
tsql_output_clause INTO insert_target tsql_output_into_target_columns
from_clause
where_or_current_clause
{
$$ = tsql_update_output_into_cte_transformation($1, NULL, $3, $6, $7, $9,
$10, $11, $12, yyscanner);
}
| opt_with_clause UPDATE tsql_top_clause relation_expr_opt_alias
| opt_with_clause UPDATE opt_top_clause relation_expr_opt_alias
tsql_opt_table_hint_expr
SET set_clause_list
tsql_output_clause INTO insert_target tsql_output_into_target_columns
Expand All @@ -1439,26 +1344,7 @@ tsql_UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
$11, $12, $13, yyscanner);
}
/* Without OUTPUT target column list */
| opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
tsql_output_clause INTO insert_target
from_clause
where_or_current_clause
{
$$ = tsql_update_output_into_cte_transformation($1, NULL, $3, $5, $6, $8,
NIL, $9, $10, yyscanner);
}
| opt_with_clause UPDATE relation_expr_opt_alias
tsql_table_hint_expr
SET set_clause_list
tsql_output_clause INTO insert_target
from_clause
where_or_current_clause
{
$$ = tsql_update_output_into_cte_transformation($1, NULL, $3, $6, $7, $9,
NIL, $10, $11, yyscanner);
}
| opt_with_clause UPDATE tsql_top_clause relation_expr_opt_alias
| opt_with_clause UPDATE opt_top_clause relation_expr_opt_alias
tsql_opt_table_hint_expr
SET set_clause_list
tsql_output_clause INTO insert_target
Expand Down Expand Up @@ -3253,20 +3139,11 @@ tsql_DeleteStmt: opt_with_clause DELETE_P opt_top_clause opt_from relation_expr_
tsql_opt_table_hint_expr tsql_output_clause from_clause where_or_current_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
tsql_reset_update_delete_globals();
n->relation = $5;
tsql_update_delete_stmt_from_clause_alias(n->relation, $8);
if ($8 != NULL && IsA(linitial($8), JoinExpr))
{
n = (DeleteStmt*)tsql_update_delete_stmt_with_join(
(Node*)n, $8, $9, $3, $5,
yyscanner);
}
else
{
n->limitCount = $3;
n->usingClause = $8;
n->whereClause = $9;
}
n->limitCount = $3;
n->usingClause = $8;
n->whereClause = $9;
n->returningList = $7;
n->withClause = $1;
$$ = (Node *)n;
Expand Down
8 changes: 6 additions & 2 deletions contrib/babelfishpg_tsql/src/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -995,9 +995,13 @@ handle_returning_qualifiers(Query *query, List *returningList, ParseState *pstat
field1 = (Node *) linitial(cref->fields);
qualifier = strVal(field1);

if ((command == CMD_INSERT && !strcmp(qualifier, "inserted"))
|| (command == CMD_DELETE && !strcmp(qualifier, "deleted")))
if (command == CMD_INSERT && !strcmp(qualifier, "inserted"))
cref->fields = list_delete_first(cref->fields);
else if (command == CMD_DELETE && !strcmp(qualifier, "deleted"))
{
Assert(pstate->p_target_nsitem->p_names->aliasname);
linitial(cref->fields) = makeString(pstate->p_target_nsitem->p_names->aliasname);
}
}
}
else if (IsA(node, A_Expr))
Expand Down
Loading

0 comments on commit de275ea

Please sign in to comment.