Skip to content

add plpgsql-dynexecute statement for CREATE FUNCTION#2350

Merged
jennifersp merged 5 commits intomainfrom
jennifer/fix
Feb 19, 2026
Merged

add plpgsql-dynexecute statement for CREATE FUNCTION#2350
jennifersp merged 5 commits intomainfrom
jennifer/fix

Conversation

@jennifersp
Copy link
Copy Markdown
Contributor

Also fixes:

  • type resolution in DECLARE
  • add support for TG_OP special variable usage for triggers

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 18, 2026

Main PR
covering_index_scan_postgres 559.47/s 526.16/s -6.0%
index_join_postgres 120.24/s 111.30/s -7.5%
index_join_scan_postgres 182.51/s 173.86/s -4.8%
index_scan_postgres 11.29/s 11.02/s -2.4%
oltp_point_select 2309.44/s 2227.65/s -3.6%
oltp_read_only 1697.06/s 1642.09/s -3.3%
select_random_points 106.79/s 102.26/s -4.3%
select_random_ranges 418.32/s 401.86/s -4.0%
table_scan_postgres 11.06/s 10.80/s -2.4%
types_table_scan_postgres 5.06/s 5.02/s -0.8%

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 18, 2026

Main PR
Total 42090 42090
Successful 17588 17642
Failures 24502 24448
Partial Successes1 5585 5572
Main PR
Successful 41.7866% 41.9149%
Failures 58.2134% 58.0851%

${\color{lightgreen}Progressions (61)}$

alter_table

QUERY: CREATE FUNCTION check_ddl_rewrite(p_tablename regclass, p_ddl text)
RETURNS boolean
LANGUAGE plpgsql AS $$
DECLARE
    v_relfilenode oid;
BEGIN
    v_relfilenode := relfilenode FROM pg_class WHERE oid = p_tablename;

    EXECUTE p_ddl;

    RETURN v_relfilenode <> (SELECT relfilenode FROM pg_class WHERE oid = p_tablename);
END;
$$;
QUERY: DROP FUNCTION check_ddl_rewrite(regclass, text);
QUERY: CREATE TYPE tt_t0 AS (z inet, x int, y numeric(8,2));
QUERY: create or replace function func_part_attach() returns trigger
  language plpgsql as $$
  begin
    execute 'create table tab_part_attach_1 (a int)';
    execute 'alter table tab_part_attach attach partition tab_part_attach_1 for values in (1)';
    return null;
  end $$;
QUERY: drop function func_part_attach();

collate.icu.utf8

QUERY: SELECT mylt2('a', 'B') as f;
QUERY: SELECT mylt2('a', 'B' collate "POSIX") as f;

create_aggregate

QUERY: create function aggf_trans(aggtype[],integer,integer,text) returns aggtype[]
as 'select array_append($1,ROW($2,$3,$4)::aggtype)'
language sql strict immutable;
QUERY: create function aggfns_trans(aggtype[],integer,integer,text) returns aggtype[]
as 'select array_append($1,ROW($2,$3,$4)::aggtype)'
language sql immutable;

create_index

QUERY: CREATE FUNCTION predicate_stable() RETURNS bool IMMUTABLE
LANGUAGE plpgsql AS $$
BEGIN
  EXECUTE 'SELECT txid_current()';
  RETURN true;
END; $$;
QUERY: DROP FUNCTION predicate_stable();
QUERY: CREATE OR REPLACE FUNCTION create_relfilenode_part(relname text, indname text)
  RETURNS VOID AS
  $func$
  BEGIN
  EXECUTE format('
    CREATE TABLE %I AS
      SELECT oid, relname, relfilenode, relkind, reltoastrelid
      FROM pg_class
      WHERE oid IN
         (SELECT relid FROM pg_partition_tree(''%I''));',
	 relname, indname);
  END
  $func$ LANGUAGE plpgsql;
QUERY: DROP FUNCTION create_relfilenode_part;

create_table

QUERY: create or replace function func_part_create() returns trigger
  language plpgsql as $$
  begin
    execute 'create table tab_part_create_1 partition of tab_part_create for values in (1)';
    return null;
  end $$;
QUERY: drop function func_part_create();

create_view

QUERY: CREATE VIEW unspecified_types AS
  SELECT 42 as i, 42.5 as num, 'foo' as u, 'foo'::unknown as u2, null as n;

groupingsets

QUERY: create function gstest_data(v integer, out a integer, out b integer)
  returns setof record
  as $f$
    begin
      return query select v, i from generate_series(1,3) i;
    end;
  $f$ language plpgsql;

incremental_sort

QUERY: create or replace function explain_analyze_inc_sort_nodes(query text)
returns jsonb language plpgsql
as
$$
declare
  elements jsonb;
  element jsonb;
  matching_nodes jsonb := '[]'::jsonb;
begin
  execute 'explain (analyze, costs off, summary off, timing off, format ''json'') ' || query into strict elements;
  while jsonb_array_length(elements) > 0 loop
    element := elements->0;
    elements := elements - 0;
    case jsonb_typeof(element)
    when 'array' then
      if jsonb_array_length(element) > 0 then
        elements := elements || element;
      end if;
    when 'object' then
      if element ? 'Plan' then
        elements := elements || jsonb_build_array(element->'Plan');
        element := element - 'Plan';
      else
        if element ? 'Plans' then
          elements := elements || jsonb_build_array(element->'Plans');
          element := element - 'Plans';
        end if;
        if (element->>'Node Type')::text = 'Incremental Sort' then
          matching_nodes := matching_nodes || element;
        end if;
      end if;
    end case;
  end loop;
  return matching_nodes;
end;
$$;

plpgsql

QUERY: create function f1(x anyelement) returns anyarray as $$
begin
  return array[x + 1, x + 2];
end$$ language plpgsql;
QUERY: create function f1(x anyarray) returns anyelement as $$
begin
  return x[1];
end$$ language plpgsql;
QUERY: create function duplic(in i anyelement, out j anyelement, out k anyarray) as $$
begin
  j := i;
  k := array[j,j];
  return;
end$$ language plpgsql;
QUERY: create or replace function composrec() returns record as $$
declare
  v record;
begin
  v := (1, 'hello');
  return v;
end;
$$ language plpgsql;
QUERY: create or replace function composrec() returns record as $$
begin
  return (1, 'hello');
end;
$$ language plpgsql;
QUERY: select composrec();
QUERY: drop function composrec();
QUERY: CREATE FUNCTION leaker_2(fail BOOL, OUT error_code INTEGER, OUT new_id INTEGER)
  RETURNS RECORD AS $$
BEGIN
  IF fail THEN
    RAISE EXCEPTION 'fail ...';
  END IF;
  error_code := 1;
  new_id := 1;
  RETURN;
END;
$$ LANGUAGE plpgsql;
QUERY: CREATE FUNCTION nonsimple_expr_test() RETURNS text[] AS $$
DECLARE
  arr text[];
  lr text;
  i integer;
BEGIN
  arr := array[array['foo','bar'], array['baz', 'quux']];
  lr := 'fool';
  i := 1;
  -- use sub-SELECTs to make expressions non-simple
  arr[(SELECT i)][(SELECT i+1)] := (SELECT lr);
  RETURN arr;
END;
$$ LANGUAGE plpgsql;
QUERY: DROP FUNCTION nonsimple_expr_test();
QUERY: create function arrayassign1() returns text[] language plpgsql as $$
declare
 r record;
begin
  r := row(12, '{foo,bar,baz}')::rtype;
  r.ar[2] := 'replace';
  return r.ar;
end$$;
QUERY: drop function arrayassign1();
QUERY: create function returns_rw_array(int) returns int[]
language plpgsql as $$
  declare r int[];
  begin r := array[$1, $1]; return r; end;
$$ stable;
QUERY: create function consumes_rw_array(int[]) returns int
language plpgsql as $$
  begin return $1[1]; end;
$$ stable;
QUERY: create function plpgsql_arr_domain_check(val int[]) returns boolean as $$
begin return val[1] > 0; end
$$ language plpgsql immutable;
QUERY: create domain plpgsql_arr_domain as int[] check(plpgsql_arr_domain_check(value));

polymorphism

QUERY: create function polyf(x anyelement) returns anyarray as $$
  select array[x + 1, x + 2]
$$ language sql;
QUERY: create function polyf(x anyarray) returns anyelement as $$
  select x[1]
$$ language sql;
QUERY: CREATE FUNCTION stfp(anyarray) RETURNS anyarray AS
'select $1' LANGUAGE SQL;
QUERY: CREATE FUNCTION stfnp(int[]) RETURNS int[] AS
'select $1' LANGUAGE SQL;
QUERY: CREATE FUNCTION tfp(anyarray,anyelement) RETURNS anyarray AS
'select $1 || $2' LANGUAGE SQL;
QUERY: CREATE FUNCTION tfnp(int[],int) RETURNS int[] AS
'select $1 || $2' LANGUAGE SQL;

Footnotes

  1. These are tests that we're marking as Successful, however they do not match the expected output in some way. This is due to small differences, such as different wording on the error messages, or the column names being incorrect while the data itself is correct.

Copy link
Copy Markdown
Collaborator

@Hydrocharged Hydrocharged left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment thread server/ast/create_function.go Outdated
@jennifersp jennifersp enabled auto-merge February 19, 2026 18:48
@jennifersp jennifersp disabled auto-merge February 19, 2026 19:21
@jennifersp jennifersp merged commit 43b468c into main Feb 19, 2026
17 checks passed
@jennifersp jennifersp deleted the jennifer/fix branch February 19, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants