Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion src/backend/distributed/deparser/ruleutils_15.c
Original file line number Diff line number Diff line change
Expand Up @@ -7093,7 +7093,8 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Assert(IsA(con, Const) &&
con->consttype == TEXTOID &&
!con->constisnull);
appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
appendStringInfoString(buf,
quote_identifier(TextDatumGetCString(con->constvalue)));
}
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
Expand Down
3 changes: 2 additions & 1 deletion src/backend/distributed/deparser/ruleutils_16.c
Original file line number Diff line number Diff line change
Expand Up @@ -7199,7 +7199,8 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Assert(IsA(con, Const) &&
con->consttype == TEXTOID &&
!con->constisnull);
appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
appendStringInfoString(buf,
quote_identifier(TextDatumGetCString(con->constvalue)));
}
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
Expand Down
3 changes: 2 additions & 1 deletion src/backend/distributed/deparser/ruleutils_17.c
Original file line number Diff line number Diff line change
Expand Up @@ -7644,7 +7644,8 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
Assert(IsA(con, Const) &&
con->consttype == TEXTOID &&
!con->constisnull);
appendStringInfoString(buf, TextDatumGetCString(con->constvalue));
appendStringInfoString(buf,
quote_identifier(TextDatumGetCString(con->constvalue)));
}
appendStringInfoString(buf, " FROM ");
get_rule_expr((Node *) lsecond(expr->args), context, false);
Expand Down
40 changes: 40 additions & 0 deletions src/test/regress/expected/extract_deparse.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--
-- EXTRACT_DEPARSE
--
CREATE SCHEMA extract_deparse;
SET search_path TO extract_deparse;
CREATE TABLE extract_deparse_source (id int, ts timestamp);
SELECT create_distributed_table('extract_deparse_source', 'id',
shard_count => 1, colocate_with => 'none');
create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO extract_deparse_source VALUES (1, timestamp '2026-01-01');
-- EXTRACT accepts any string as its field name. Verify Citus quotes that field
-- when deparsing task SQL, so text resembling a second statement remains data.
-- PG19 has equivalent coverage in pg19.sql.
DO $$
BEGIN
IF current_setting('server_version_num')::int < 190000 THEN
PERFORM EXTRACT('year FROM timestamp ''2000-01-01''); CREATE TABLE injected(); --' FROM ts)
FROM extract_deparse_source
WHERE id = 1;
END IF;
EXCEPTION
WHEN invalid_parameter_value THEN NULL;
END
$$;
SELECT bool_and(result::boolean) AS extract_field_injection_blocked
FROM run_command_on_workers($$
SELECT to_regclass('extract_deparse.injected') IS NULL
$$);
extract_field_injection_blocked
---------------------------------------------------------------------
t
(1 row)

SET client_min_messages TO ERROR;
DROP SCHEMA extract_deparse CASCADE;
RESET client_min_messages;
1 change: 1 addition & 0 deletions src/test/regress/multi_1_create_citus_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,4 @@ test: citus_cluster_changes_block
# part of the N-1 test matrix. Move back to multi_schedule at Citus 14.
# ----------
test: allow_unsafe_insert_select_pushdown
test: extract_deparse
35 changes: 35 additions & 0 deletions src/test/regress/sql/extract_deparse.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--
-- EXTRACT_DEPARSE
--

CREATE SCHEMA extract_deparse;
SET search_path TO extract_deparse;

CREATE TABLE extract_deparse_source (id int, ts timestamp);
SELECT create_distributed_table('extract_deparse_source', 'id',
shard_count => 1, colocate_with => 'none');
INSERT INTO extract_deparse_source VALUES (1, timestamp '2026-01-01');

-- EXTRACT accepts any string as its field name. Verify Citus quotes that field
-- when deparsing task SQL, so text resembling a second statement remains data.
-- PG19 has equivalent coverage in pg19.sql.
DO $$
BEGIN
IF current_setting('server_version_num')::int < 190000 THEN
PERFORM EXTRACT('year FROM timestamp ''2000-01-01''); CREATE TABLE injected(); --' FROM ts)
FROM extract_deparse_source
WHERE id = 1;
END IF;
EXCEPTION
WHEN invalid_parameter_value THEN NULL;
END
$$;

SELECT bool_and(result::boolean) AS extract_field_injection_blocked
FROM run_command_on_workers($$
SELECT to_regclass('extract_deparse.injected') IS NULL
$$);

SET client_min_messages TO ERROR;
DROP SCHEMA extract_deparse CASCADE;
RESET client_min_messages;
Loading