Skip to content

add plpgsql-dynexecute statement for CREATE FUNCTION#2350

Open
jennifersp wants to merge 2 commits intomainfrom
jennifer/fix
Open

add plpgsql-dynexecute statement for CREATE FUNCTION#2350
jennifersp wants to merge 2 commits intomainfrom
jennifer/fix

Conversation

@jennifersp
Copy link
Contributor

Also fixes:

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

@github-actions
Copy link
Contributor

Main PR
covering_index_scan_postgres 552.00/s 564.76/s +2.3%
index_join_postgres 118.59/s 118.02/s -0.5%
index_join_scan_postgres 174.05/s 175.81/s +1.0%
index_scan_postgres 10.93/s 11.04/s +1.0%
oltp_point_select 2260.51/s 2235.15/s -1.2%
oltp_read_only 1671.98/s 1674.66/s +0.1%
select_random_points 103.73/s 107.51/s +3.6%
select_random_ranges 426.80/s 419.53/s -1.8%
table_scan_postgres 10.67/s 10.91/s +2.2%
types_table_scan_postgres 4.92/s 5.04/s +2.4%

@github-actions
Copy link
Contributor

Main PR
Total 42090 42090
Successful 17571 17583
Failures 24519 24507
Partial Successes1 5585 5583
Main PR
Successful 41.7463% 41.7748%
Failures 58.2537% 58.2252%

${\color{red}Regressions (3)}$

rangefuncs

QUERY:          CREATE FUNCTION getrngfunc9(int) RETURNS rngfunc AS 'DECLARE rngfunctup rngfunc%ROWTYPE; BEGIN SELECT * into rngfunctup FROM rngfunc WHERE rngfuncid = $1; RETURN rngfunctup; END;' LANGUAGE plpgsql;
RECEIVED ERROR: expected a tree.CastExpr, but found *tree.BinaryExpr
QUERY:          CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc9(1);
RECEIVED ERROR: table function: 'getrngfunc9' not found (errno 1105) (sqlstate HY000)
QUERY:          DROP FUNCTION getrngfunc9(int);
RECEIVED ERROR: function getrngfunc9(INTEGER) does not exist (errno 1105) (sqlstate HY000)

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

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 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_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();

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;
$$;

truncate

QUERY: CREATE FUNCTION trunctrigger() RETURNS trigger as $$
declare c bigint;
begin
    execute 'select count(*) from ' || quote_ident(tg_table_name) into c;
    insert into trunc_trigger_log values
      (TG_OP, TG_LEVEL, TG_WHEN, TG_ARGV[0], tg_table_name, c);
    return null;
end;
$$ LANGUAGE plpgsql;
QUERY: DROP FUNCTION trunctrigger();

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
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 on lines +225 to +240
func getDoltgresType(ctx *Context, rt tree.ResolvableTypeReference, mayBeTrigger bool) (*pgtypes.DoltgresType, error) {
switch argType := rt.(type) {
case *types.T:
return pgtypes.NewUnresolvedDoltgresType("", strings.ToLower(argType.Name())), nil
case *tree.UnresolvedObjectName:
if mayBeTrigger && argType.NumParts == 1 && argType.SQLString() == "trigger" {
return pgtypes.Trigger, nil
} else {
_, retType, err := nodeResolvableTypeReference(ctx, argType)
return retType, err
}
default:
// return nil, fmt.Errorf("unsupported ResolvableTypeReference type: %T", typ)
return pgtypes.NewUnresolvedDoltgresType("", strings.ToLower(argType.SQLString())), nil
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we should fold this into nodeResolvableTypeReference. The only real difference appears to be that, when mayBeTrigger is true, then we do a trigger check. Instead, that could just happen at the call site (since it's only valid in one location anyway), and we pass to nodeResolvableTypeReference in all other cases.

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

Comments