Skip to content

Instantly share code, notes, and snippets.

@bhvngt
Created July 11, 2022 12:04
Show Gist options
  • Save bhvngt/d351c6a19b388e9d365484ca9672c4fa to your computer and use it in GitHub Desktop.
Save bhvngt/d351c6a19b388e9d365484ca9672c4fa to your computer and use it in GitHub Desktop.
docker realtime logs
realtime-realtime-1 | 2022-07-11 11:56:01.778 [error] Postgrex.Protocol (#PID<0.233.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:01.778 [error] Postgrex.Protocol (#PID<0.232.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:01.900 [error] Postgrex.Protocol (#PID<0.232.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:01.981 [error] Postgrex.Protocol (#PID<0.233.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:02.219 [error] Postgrex.Protocol (#PID<0.232.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:02.564 [error] Postgrex.Protocol (#PID<0.233.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:02.797 [error] Postgrex.Protocol (#PID<0.232.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:03.388 [error] Postgrex.Protocol (#PID<0.232.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:03.438 [error] Postgrex.Protocol (#PID<0.233.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:04.445 [error] Postgrex.Protocol (#PID<0.232.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:05.184 [error] Postgrex.Protocol (#PID<0.233.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (db:5432): connection refused - :econnrefused
realtime-realtime-1 | 2022-07-11 11:56:07.512 [info] == Running 20211116024918 Realtime.RLS.Repo.Migrations.CreateRealtimeSubscriptionTable.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.512 [info] execute "create type realtime.equality_op as enum(\n 'eq', 'neq', 'lt', 'lte', 'gt', 'gte'\n );"
realtime-realtime-1 | 2022-07-11 11:56:07.527 [info] execute "create type realtime.user_defined_filter as (\n column_name text,\n op realtime.equality_op,\n value text\n );"
realtime-realtime-1 | 2022-07-11 11:56:07.534 [info] execute "create table realtime.subscription (\n -- Tracks which users are subscribed to each table\n id bigint not null generated always as identity,\n user_id uuid not null,\n -- Populated automatically by trigger. Required to enable auth.email()\n email varchar(255),\n entity regclass not null,\n filters realtime.user_defined_filter[] not null default '{}',\n created_at timestamp not null default timezone('utc', now()),\n\n constraint pk_subscription primary key (id),\n unique (entity, user_id, filters)\n )"
realtime-realtime-1 | 2022-07-11 11:56:07.568 [info] execute "create index ix_realtime_subscription_entity on realtime.subscription using hash (entity)"
realtime-realtime-1 | 2022-07-11 11:56:07.572 [info] == Migrated 20211116024918 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.603 [info] == Running 20211116045059 Realtime.RLS.Repo.Migrations.CreateRealtimeCheckFiltersTrigger.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.603 [info] execute "create function realtime.subscription_check_filters()\n returns trigger\n language plpgsql\n as $$\n /*\n Validates that the user defined filters for a subscription:\n - refer to valid columns that 'authenticated' may access\n - values are coercable to the correct column type\n */\n declare\n col_names text[] = coalesce(\n array_agg(c.column_name order by c.ordinal_position),\n '{}'::text[]\n )\n from\n information_schema.columns c\n where\n (quote_ident(c.table_schema) || '.' || quote_ident(c.table_name))::regclass = new.entity\n and pg_catalog.has_column_privilege('authenticated', new.entity, c.column_name, 'SELECT');\n filter realtime.user_defined_filter;\n col_type text;\n begin\n for filter in select * from unnest(new.filters) loop\n -- Filtered column is valid\n if not filter.column_name = any(col_names) then\n raise exception 'invalid column for filter %', filter.column_name;\n end if;\n\n -- Type is sanitized and safe for string interpolation\n col_type = (\n select atttypid::regtype\n from pg_catalog.pg_attribute\n where attrelid = new.entity\n and attname = filter.column_name\n )::text;\n if col_type is null then\n raise exception 'failed to lookup type for column %', filter.column_name;\n end if;\n -- raises an exception if value is not coercable to type\n perform format('select %s::%I', filter.value, col_type);\n end loop;\n\n -- Apply consistent order to filters so the unique constraint on\n -- (user_id, entity, filters) can't be tricked by a different filter order\n new.filters = coalesce(\n array_agg(f order by f.column_name, f.op, f.value),\n '{}'\n ) from unnest(new.filters) f;\n\n return new;\n end;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.614 [info] execute "create trigger tr_check_filters\n before insert or update on realtime.subscription\n for each row\n execute function realtime.subscription_check_filters();"
realtime-realtime-1 | 2022-07-11 11:56:07.618 [info] == Migrated 20211116045059 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.625 [info] == Running 20211116050929 Realtime.RLS.Repo.Migrations.CreateRealtimeQuoteWal2jsonFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.626 [info] execute "create function realtime.quote_wal2json(entity regclass)\n returns text\n language sql\n immutable\n strict\n as $$\n select\n (\n select string_agg('' || ch,'')\n from unnest(string_to_array(nsp.nspname::text, null)) with ordinality x(ch, idx)\n where\n not (x.idx = 1 and x.ch = '\"')\n and not (\n x.idx = array_length(string_to_array(nsp.nspname::text, null), 1)\n and x.ch = '\"'\n )\n )\n || '.'\n || (\n select string_agg('' || ch,'')\n from unnest(string_to_array(pc.relname::text, null)) with ordinality x(ch, idx)\n where\n not (x.idx = 1 and x.ch = '\"')\n and not (\n x.idx = array_length(string_to_array(nsp.nspname::text, null), 1)\n and x.ch = '\"'\n )\n )\n from\n pg_class pc\n join pg_namespace nsp\n on pc.relnamespace = nsp.oid\n where\n pc.oid = entity\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.637 [info] == Migrated 20211116050929 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.673 [info] == Running 20211116051442 Realtime.RLS.Repo.Migrations.CreateRealtimeCheckEqualityOpFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.674 [info] execute "create function realtime.check_equality_op(\n op realtime.equality_op,\n type_ regtype,\n val_1 text,\n val_2 text\n )\n returns bool\n immutable\n language plpgsql\n as $$\n /*\n Casts *val_1* and *val_2* as type *type_* and check the *op* condition for truthiness\n */\n declare\n op_symbol text = (\n case\n when op = 'eq' then '='\n when op = 'neq' then '!='\n when op = 'lt' then '<'\n when op = 'lte' then '<='\n when op = 'gt' then '>'\n when op = 'gte' then '>='\n else 'UNKNOWN OP'\n end\n );\n res boolean;\n begin\n execute format('select %L::'|| type_::text || ' ' || op_symbol || ' %L::'|| type_::text, val_1, val_2) into res;\n return res;\n end;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.677 [info] == Migrated 20211116051442 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.679 [info] == Running 20211116212300 Realtime.RLS.Repo.Migrations.CreateRealtimeBuildPreparedStatementSqlFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.679 [info] execute "create type realtime.wal_column as (\n name text,\n type text,\n value jsonb,\n is_pkey boolean,\n is_selectable boolean\n );"
realtime-realtime-1 | 2022-07-11 11:56:07.681 [info] execute "create function realtime.build_prepared_statement_sql(\n prepared_statement_name text,\n entity regclass,\n columns realtime.wal_column[]\n )\n returns text\n language sql\n as $$\n /*\n Builds a sql string that, if executed, creates a prepared statement to\n tests retrive a row from *entity* by its primary key columns.\n\n Example\n select realtime.build_prepared_statment_sql('public.notes', '{\"id\"}'::text[], '{\"bigint\"}'::text[])\n */\n select\n 'prepare ' || prepared_statement_name || ' as\n select\n exists(\n select\n 1\n from\n ' || entity || '\n where\n ' || string_agg(quote_ident(pkc.name) || '=' || quote_nullable(pkc.value) , ' and ') || '\n )'\n from\n unnest(columns) pkc\n where\n pkc.is_pkey\n group by\n entity\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.684 [info] == Migrated 20211116212300 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.687 [info] == Running 20211116213355 Realtime.RLS.Repo.Migrations.CreateRealtimeCastFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.687 [info] execute "create function realtime.cast(val text, type_ regtype)\n returns jsonb\n immutable\n language plpgsql\n as $$\n declare\n res jsonb;\n begin\n execute format('select to_jsonb(%L::'|| type_::text || ')', val) into res;\n return res;\n end\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.688 [info] == Migrated 20211116213355 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.690 [info] == Running 20211116213934 Realtime.RLS.Repo.Migrations.CreateRealtimeIsVisibleThroughFiltersFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.690 [info] execute "create function realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[])\n returns bool\n language sql\n immutable\n as $$\n /*\n Should the record be visible (true) or filtered out (false) after *filters* are applied\n */\n select\n -- Default to allowed when no filters present\n coalesce(\n sum(\n realtime.check_equality_op(\n op:=f.op,\n type_:=col.type::regtype,\n -- cast jsonb to text\n val_1:=col.value #>> '{}',\n val_2:=f.value\n )::int\n ) = count(1),\n true\n )\n from\n unnest(filters) f\n join unnest(columns) col\n on f.column_name = col.name;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.693 [info] == Migrated 20211116213934 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.695 [info] == Running 20211116214523 Realtime.RLS.Repo.Migrations.CreateRealtimeApplyRlsFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.695 [info] execute "create type realtime.action as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'ERROR');"
realtime-realtime-1 | 2022-07-11 11:56:07.697 [info] execute "create type realtime.wal_rls as (\n wal jsonb,\n is_rls_enabled boolean,\n users uuid[],\n errors text[]\n );"
realtime-realtime-1 | 2022-07-11 11:56:07.700 [info] execute "create function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n when 'T' then 'TRUNCATE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n -- Subscription vars\n user_id uuid;\n email varchar(255);\n user_has_access bool;\n is_visible_to_user boolean;\n visible_to_user_ids uuid[] = '{}';\n\n -- user subscriptions to the wal record's table\n subscriptions realtime.subscription[] =\n array_agg(sub)\n from\n realtime.subscription sub\n where\n sub.entity = entity_;\n\n -- structured info for wal's columns\n columns realtime.wal_column[] =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n pg_catalog.has_column_privilege('authenticated', entity_, x->>'name', 'SELECT')\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n -- previous identity values for update/delete\n old_columns realtime.wal_column[] =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n pg_catalog.has_column_privilege('authenticated', entity_, x->>'name', 'SELECT')\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n output jsonb;\n\n -- Error states\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n error_unauthorized boolean = not pg_catalog.has_any_column_privilege('authenticated', entity_, 'SELECT');\n\n errors text[] = case\n when error_record_exceeds_max_size then array['Error 413: Payload Too Large']\n else '{}'::text[]\n end;\n begin\n\n -- The 'authenticated' user does not have SELECT permission on any of the columns for the entity_\n if error_unauthorized is true then\n return (\n null,\n null,\n visible_to_user_ids,\n array['Error 401: Unauthorized']\n )::realtime.wal_rls;\n end if;\n\n -------------------------------\n -- Build Output JSONB Object --\n -------------------------------\n output = jsonb_build_object(\n 'schema', wal ->> 'schema',\n 'table', wal ->> 'table',\n 'type', action,\n 'commit_timestamp', (wal ->> 'timestamp')::text::timestamp with time zone,\n 'columns', (\n select\n jsonb_agg(\n jsonb_build_object(\n 'name', pa.attname,\n 'type', pt.typname\n )\n order by pa.attnum asc\n )\n from\n pg_attribute pa\n join pg_type pt\n on pa.atttypid = pt.oid\n where\n attrelid = entity_\n and attnum > 0\n and pg_catalog.has_column_privilege('authenticated', entity_, pa.attname, 'SELECT')\n )\n )\n -- Add \"record\" key for insert and update\n || case\n when error_record_exceeds_max_size then jsonb_build_object('record', '{}'::jsonb)\n when action in ('INSERT'," <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.708 [info] == Migrated 20211116214523 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.710 [info] == Running 20211122062447 Realtime.RLS.Repo.Migrations.GrantRealtimeUsageToAuthenticatedRole.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.710 [info] execute "grant usage on schema realtime to authenticated;"
realtime-realtime-1 | 2022-07-11 11:56:07.713 [info] == Migrated 20211122062447 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.716 [info] == Running 20211124070109 Realtime.RLS.Repo.Migrations.EnableRealtimeApplyRlsFunctionPostgrest9Compatibility.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.716 [info] execute "create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n when 'T' then 'TRUNCATE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n -- Subscription vars\n user_id uuid;\n email varchar(255);\n user_has_access bool;\n is_visible_to_user boolean;\n visible_to_user_ids uuid[] = '{}';\n\n -- user subscriptions to the wal record's table\n subscriptions realtime.subscription[] =\n array_agg(sub)\n from\n realtime.subscription sub\n where\n sub.entity = entity_;\n\n -- structured info for wal's columns\n columns realtime.wal_column[] =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n pg_catalog.has_column_privilege('authenticated', entity_, x->>'name', 'SELECT')\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n -- previous identity values for update/delete\n old_columns realtime.wal_column[] =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n pg_catalog.has_column_privilege('authenticated', entity_, x->>'name', 'SELECT')\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n output jsonb;\n\n -- Error states\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n error_unauthorized boolean = not pg_catalog.has_any_column_privilege('authenticated', entity_, 'SELECT');\n\n errors text[] = case\n when error_record_exceeds_max_size then array['Error 413: Payload Too Large']\n else '{}'::text[]\n end;\n begin\n\n -- The 'authenticated' user does not have SELECT permission on any of the columns for the entity_\n if error_unauthorized is true then\n return (\n null,\n null,\n visible_to_user_ids,\n array['Error 401: Unauthorized']\n )::realtime.wal_rls;\n end if;\n\n -------------------------------\n -- Build Output JSONB Object --\n -------------------------------\n output = jsonb_build_object(\n 'schema', wal ->> 'schema',\n 'table', wal ->> 'table',\n 'type', action,\n 'commit_timestamp', (wal ->> 'timestamp')::text::timestamp with time zone,\n 'columns', (\n select\n jsonb_agg(\n jsonb_build_object(\n 'name', pa.attname,\n 'type', pt.typname\n )\n order by pa.attnum asc\n )\n from\n pg_attribute pa\n join pg_type pt\n on pa.atttypid = pt.oid\n where\n attrelid = entity_\n and attnum > 0\n and pg_catalog.has_column_privilege('authenticated', entity_, pa.attname, 'SELECT')\n )\n )\n -- Add \"record\" key for insert and update\n || case\n when error_record_exceeds_max_size then jsonb_build_object('record', '{}'::jsonb)\n when action in" <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.723 [info] == Migrated 20211124070109 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.726 [info] == Running 20211202204204 Realtime.RLS.Repo.Migrations.UpdateRealtimeSubscriptionCheckFiltersFunctionSecurity.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.727 [info] execute "create or replace function realtime.subscription_check_filters()\n returns trigger\n language plpgsql\n as $$\n /*\n Validates that the user defined filters for a subscription:\n - refer to valid columns that 'authenticated' may access\n - values are coercable to the correct column type\n */\n declare\n col_names text[] = coalesce(\n array_agg(c.column_name order by c.ordinal_position),\n '{}'::text[]\n )\n from\n information_schema.columns c\n where\n (quote_ident(c.table_schema) || '.' || quote_ident(c.table_name))::regclass = new.entity\n and pg_catalog.has_column_privilege('authenticated', new.entity, c.column_name, 'SELECT');\n filter realtime.user_defined_filter;\n col_type regtype;\n begin\n for filter in select * from unnest(new.filters) loop\n -- Filtered column is valid\n if not filter.column_name = any(col_names) then\n raise exception 'invalid column for filter %', filter.column_name;\n end if;\n\n -- Type is sanitized and safe for string interpolation\n col_type = (\n select atttypid::regtype\n from pg_catalog.pg_attribute\n where attrelid = new.entity\n and attname = filter.column_name\n );\n if col_type is null then\n raise exception 'failed to lookup type for column %', filter.column_name;\n end if;\n -- raises an exception if value is not coercable to type\n perform realtime.cast(filter.value, col_type);\n end loop;\n\n -- Apply consistent order to filters so the unique constraint on\n -- (user_id, entity, filters) can't be tricked by a different filter order\n new.filters = coalesce(\n array_agg(f order by f.column_name, f.op, f.value),\n '{}'\n ) from unnest(new.filters) f;\n\n return new;\n end;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.737 [info] == Migrated 20211202204204 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.739 [info] == Running 20211202204605 Realtime.RLS.Repo.Migrations.UpdateRealtimeBuildPreparedStatementSqlFunctionForCompatibilityWithAllTypes.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.739 [info] execute "create or replace function realtime.build_prepared_statement_sql(\n prepared_statement_name text,\n entity regclass,\n columns realtime.wal_column[]\n )\n returns text\n language sql\n as $$\n /*\n Builds a sql string that, if executed, creates a prepared statement to\n tests retrive a row from *entity* by its primary key columns.\n\n Example\n select realtime.build_prepared_statment_sql('public.notes', '{\"id\"}'::text[], '{\"bigint\"}'::text[])\n */\n select\n 'prepare ' || prepared_statement_name || ' as\n select\n exists(\n select\n 1\n from\n ' || entity || '\n where\n ' || string_agg(quote_ident(pkc.name) || '=' || quote_nullable(pkc.value #>> '{}') , ' and ') || '\n )'\n from\n unnest(columns) pkc\n where\n pkc.is_pkey\n group by\n entity\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.745 [info] == Migrated 20211202204605 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.747 [info] == Running 20211210212804 Realtime.RLS.Repo.Migrations.EnableGenericSubscriptionClaims.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.748 [info] execute "truncate table realtime.subscription restart identity"
realtime-realtime-1 | 2022-07-11 11:56:07.756 [info] execute "alter table realtime.subscription\n drop constraint subscription_entity_user_id_filters_key cascade,\n drop column email cascade,\n drop column created_at cascade"
realtime-realtime-1 | 2022-07-11 11:56:07.762 [info] execute "alter table realtime.subscription rename user_id to subscription_id"
realtime-realtime-1 | 2022-07-11 11:56:07.763 [info] execute "create function realtime.to_regrole(role_name text)\n returns regrole\n immutable\n language sql\n -- required to allow use in generated clause\n as $$ select role_name::regrole $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.764 [info] execute "alter table realtime.subscription\n add column claims jsonb not null,\n add column claims_role regrole not null generated always as (realtime.to_regrole(claims ->> 'role')) stored,\n add column created_at timestamp not null default timezone('utc', now())"
realtime-realtime-1 | 2022-07-11 11:56:07.780 [info] execute "create unique index subscription_subscription_id_entity_filters_key on realtime.subscription (subscription_id, entity, filters)"
realtime-realtime-1 | 2022-07-11 11:56:07.783 [info] execute "revoke usage on schema realtime from authenticated;"
realtime-realtime-1 | 2022-07-11 11:56:07.784 [info] execute "revoke all on realtime.subscription from authenticated;"
realtime-realtime-1 | 2022-07-11 11:56:07.785 [info] execute "create or replace function realtime.subscription_check_filters()\n returns trigger\n language plpgsql\n as $$\n /*\n Validates that the user defined filters for a subscription:\n - refer to valid columns that the claimed role may access\n - values are coercable to the correct column type\n */\n declare\n col_names text[] = coalesce(\n array_agg(c.column_name order by c.ordinal_position),\n '{}'::text[]\n )\n from\n information_schema.columns c\n where\n format('%I.%I', c.table_schema, c.table_name)::regclass = new.entity\n and pg_catalog.has_column_privilege((new.claims ->> 'role'), new.entity, c.column_name, 'SELECT');\n filter realtime.user_defined_filter;\n col_type regtype;\n begin\n for filter in select * from unnest(new.filters) loop\n -- Filtered column is valid\n if not filter.column_name = any(col_names) then\n raise exception 'invalid column for filter %', filter.column_name;\n end if;\n\n -- Type is sanitized and safe for string interpolation\n col_type = (\n select atttypid::regtype\n from pg_catalog.pg_attribute\n where attrelid = new.entity\n and attname = filter.column_name\n );\n if col_type is null then\n raise exception 'failed to lookup type for column %', filter.column_name;\n end if;\n -- raises an exception if value is not coercable to type\n perform realtime.cast(filter.value, col_type);\n end loop;\n\n -- Apply consistent order to filters so the unique constraint on\n -- (subscription_id, entity, filters) can't be tricked by a different filter order\n new.filters = coalesce(\n array_agg(f order by f.column_name, f.op, f.value),\n '{}'\n ) from unnest(new.filters) f;\n\n return new;\n end;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.788 [info] execute "alter type realtime.wal_rls rename attribute users to subscription_ids cascade;"
realtime-realtime-1 | 2022-07-11 11:56:07.789 [info] execute "drop function realtime.apply_rls(jsonb, integer);"
realtime-realtime-1 | 2022-07-11 11:56:07.792 [info] execute "create function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n old_columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(old_columns) c;\n\n if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then\n return next (\n null,\n is_rls_enabled,\n -- subscriptions is already filtered by entity\n (select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),\n array['Error 400: Bad Request, no primary key']\n )::realtime.wal_rls;\n\n -- The claims role does not have SELECT permission to the primary key of entity\n elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where c.is_pkey t" <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.799 [info] == Migrated 20211210212804 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.804 [info] == Running 20211228014915 Realtime.RLS.Repo.Migrations.AddWalPayloadOnErrorsInApplyRlsFunction.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.805 [info] execute "create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n old_columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(old_columns) c;\n\n if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then\n return next (\n jsonb_build_object(\n 'schema', wal ->> 'schema',\n 'table', wal ->> 'table',\n 'type', action\n ),\n is_rls_enabled,\n -- subscriptions is already filtered by entity\n (select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),\n array['Error 400: Bad Request, no primary key']\n )::realtime.wal_rls;\n\n -- The claims role does not have SELECT permission to the primary key of entity\n elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where c.is_pkey then\n return next (\n jsonb_build_object(\n 'schema', wal ->> 'schema',\n 'table', wal ->> 'table',\n 'type', action\n ),\n " <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.810 [info] == Migrated 20211228014915 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.813 [info] == Running 20220107221237 Realtime.RLS.Repo.Migrations.UpdateChangeTimestampToIso8601ZuluFormat.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.813 [info] execute "create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n old_columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(old_columns) c;\n\n if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then\n return next (\n null,\n is_rls_enabled,\n -- subscriptions is already filtered by entity\n (select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),\n array['Error 400: Bad Request, no primary key']\n )::realtime.wal_rls;\n\n -- The claims role does not have SELECT permission to the primary key of entity\n elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where " <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.818 [info] == Migrated 20220107221237 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.820 [info] == Running 20220228202821 Realtime.RLS.Repo.Migrations.UpdateSubscriptionCheckFiltersFunctionDynamicTableName.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.820 [info] execute "create or replace function realtime.subscription_check_filters()\n returns trigger\n language plpgsql\n as $$\n /*\n Validates that the user defined filters for a subscription:\n - refer to valid columns that the claimed role may access\n - values are coercable to the correct column type\n */\n declare\n col_names text[] = coalesce(\n array_agg(c.column_name order by c.ordinal_position),\n '{}'::text[]\n )\n from\n information_schema.columns c\n where\n format('%I.%I', c.table_schema, c.table_name)::regclass = new.entity\n and pg_catalog.has_column_privilege(\n (new.claims ->> 'role'),\n format('%I.%I', c.table_schema, c.table_name)::regclass,\n c.column_name,\n 'SELECT'\n );\n filter realtime.user_defined_filter;\n col_type regtype;\n begin\n for filter in select * from unnest(new.filters) loop\n -- Filtered column is valid\n if not filter.column_name = any(col_names) then\n raise exception 'invalid column for filter %', filter.column_name;\n end if;\n\n -- Type is sanitized and safe for string interpolation\n col_type = (\n select atttypid::regtype\n from pg_catalog.pg_attribute\n where attrelid = new.entity\n and attname = filter.column_name\n );\n if col_type is null then\n raise exception 'failed to lookup type for column %', filter.column_name;\n end if;\n -- raises an exception if value is not coercable to type\n perform realtime.cast(filter.value, col_type);\n end loop;\n\n -- Apply consistent order to filters so the unique constraint on\n -- (subscription_id, entity, filters) can't be tricked by a different filter order\n new.filters = coalesce(\n array_agg(f order by f.column_name, f.op, f.value),\n '{}'\n ) from unnest(new.filters) f;\n\n return new;\n end;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.822 [info] == Migrated 20220228202821 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.824 [info] == Running 20220312004840 Realtime.RLS.Repo.Migrations.UpdateApplyRlsFunctionToApplyIso8601.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.824 [info] execute "create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n realtime.cast((x->'value') #>> '{}', (x->>'type')::regtype),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n old_columns =\n array_agg(\n (\n c.name,\n c.type,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(old_columns) c;\n\n if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then\n return next (\n null,\n is_rls_enabled,\n -- subscriptions is already filtered by entity\n (select array_agg(s.subscription_id) from unnest(subscriptions) as s where claims_role = working_role),\n array['Error 400: Bad Request, no primary key']\n )::realtime.wal_rls;\n\n -- The claims role does not have SELECT permission to the primary key of entity\n elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where " <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.828 [info] == Migrated 20220312004840 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.830 [info] == Running 20220603231003 Realtime.RLS.Repo.Migrations.AddQuotedRegtypesSupport.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.830 [info] execute "drop type if exists realtime.wal_column cascade;"
realtime-realtime-1 | 2022-07-11 11:56:07.835 [info] drop cascades to 2 other objects
realtime-realtime-1 | 2022-07-11 11:56:07.835 [info] execute "\n create type realtime.wal_column as (\n name text,\n type_name text,\n type_oid oid,\n value jsonb,\n is_pkey boolean,\n is_selectable boolean\n );\n "
realtime-realtime-1 | 2022-07-11 11:56:07.837 [info] execute "\n create or replace function realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[])\n returns bool\n language sql\n immutable\n as $$\n /*\n Should the record be visible (true) or filtered out (false) after *filters* are applied\n */\n select\n -- Default to allowed when no filters present\n coalesce(\n sum(\n realtime.check_equality_op(\n op:=f.op,\n type_:=col.type_oid::regtype,\n -- cast jsonb to text\n val_1:=col.value #>> '{}',\n val_2:=f.value\n )::int\n ) = count(1),\n true\n )\n from\n unnest(filters) f\n join unnest(columns) col\n on f.column_name = col.name;\n $$;"
realtime-realtime-1 | 2022-07-11 11:56:07.840 [info] execute "\n create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n x->>'typeoid',\n realtime.cast(\n (x->'value') #>> '{}',\n (x->>'typeoid')::regtype\n ),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n x->>'typeoid',\n realtime.cast(\n (x->'value') #>> '{}',\n (x->>'typeoid')::regtype\n ),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type_name,\n c.type_oid,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n old_columns =\n array_agg(\n (\n c.name,\n " <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.844 [info] == Migrated 20220603231003 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.847 [info] == Running 20220603232444 Realtime.RLS.Repo.Migrations.AddOutputForDataLessThanEqual64BytesWhenPayloadTooLarge.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.847 [info] execute "\n create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n x->>'typeoid',\n realtime.cast(\n (x->'value') #>> '{}',\n (x->>'typeoid')::regtype\n ),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n x->>'typeoid',\n realtime.cast(\n (x->'value') #>> '{}',\n (x->>'typeoid')::regtype\n ),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type_name,\n c.type_oid,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n old_columns =\n array_agg(\n (\n c.name,\n c.type_name,\n c.type_oid,\n c.value,\n c.is_pkey,\n pg_ca" <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.853 [info] == Migrated 20220603232444 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:07.855 [info] == Running 20220615214548 Realtime.RLS.Repo.Migrations.AddQuotedRegtypesBackwardCompatibilitySupport.change/0 forward
realtime-realtime-1 | 2022-07-11 11:56:07.855 [info] execute "\n create or replace function realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[])\n returns bool\n language sql\n immutable\n as $$\n /*\n Should the record be visible (true) or filtered out (false) after *filters* are applied\n */\n select\n -- Default to allowed when no filters present\n coalesce(\n sum(\n realtime.check_equality_op(\n op:=f.op,\n type_:=coalesce(\n col.type_oid::regtype, -- null when wal2json version <= 2.4\n col.type_name::regtype\n ),\n -- cast jsonb to text\n val_1:=col.value #>> '{}',\n val_2:=f.value\n )::int\n ) = count(1),\n true\n )\n from\n unnest(filters) f\n join unnest(columns) col\n on f.column_name = col.name;\n $$;\n "
realtime-realtime-1 | 2022-07-11 11:56:07.858 [info] execute "\n create or replace function realtime.apply_rls(wal jsonb, max_record_bytes int = 1024 * 1024)\n returns setof realtime.wal_rls\n language plpgsql\n volatile\n as $$\n declare\n -- Regclass of the table e.g. public.notes\n entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;\n\n -- I, U, D, T: insert, update ...\n action realtime.action = (\n case wal ->> 'action'\n when 'I' then 'INSERT'\n when 'U' then 'UPDATE'\n when 'D' then 'DELETE'\n else 'ERROR'\n end\n );\n\n -- Is row level security enabled for the table\n is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;\n\n subscriptions realtime.subscription[] = array_agg(subs)\n from\n realtime.subscription subs\n where\n subs.entity = entity_;\n\n -- Subscription vars\n roles regrole[] = array_agg(distinct us.claims_role)\n from\n unnest(subscriptions) us;\n\n working_role regrole;\n claimed_role regrole;\n claims jsonb;\n\n subscription_id uuid;\n subscription_has_access bool;\n visible_to_subscription_ids uuid[] = '{}';\n\n -- structured info for wal's columns\n columns realtime.wal_column[];\n -- previous identity values for update/delete\n old_columns realtime.wal_column[];\n\n error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;\n\n -- Primary jsonb output for record\n output jsonb;\n\n begin\n perform set_config('role', null, true);\n\n columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n x->>'typeoid',\n realtime.cast(\n (x->'value') #>> '{}',\n coalesce(\n (x->>'typeoid')::regtype, -- null when wal2json version <= 2.4\n (x->>'type')::regtype\n )\n ),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'columns') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n old_columns =\n array_agg(\n (\n x->>'name',\n x->>'type',\n x->>'typeoid',\n realtime.cast(\n (x->'value') #>> '{}',\n coalesce(\n (x->>'typeoid')::regtype, -- null when wal2json version <= 2.4\n (x->>'type')::regtype\n )\n ),\n (pks ->> 'name') is not null,\n true\n )::realtime.wal_column\n )\n from\n jsonb_array_elements(wal -> 'identity') x\n left join jsonb_array_elements(wal -> 'pk') pks\n on (x ->> 'name') = (pks ->> 'name');\n\n for working_role in select * from unnest(roles) loop\n\n -- Update `is_selectable` for columns and old_columns\n columns =\n array_agg(\n (\n c.name,\n c.type_name,\n c.type_oid,\n c.value,\n c.is_pkey,\n pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')\n )::realtime.wal_column\n )\n from\n unnest(columns) c;\n\n " <> ...
realtime-realtime-1 | 2022-07-11 11:56:07.863 [info] == Migrated 20220615214548 in 0.0s
realtime-realtime-1 | 2022-07-11 11:56:11.275 [info] Running RealtimeWeb.Endpoint with cowboy 2.8.0 at :::4000 (http)
realtime-realtime-1 | 2022-07-11 11:56:11.275 [info] Access RealtimeWeb.Endpoint at http://localhost:4000
realtime-realtime-1 | 2022-07-11 11:56:11.354 [info] CONNECTED TO RealtimeWeb.UserSocket in 113µs
realtime-realtime-1 | Transport: :websocket
realtime-realtime-1 | Serializer: Phoenix.Socket.V1.JSONSerializer
realtime-realtime-1 | Parameters: %{"apikey" => "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXV0aGVudGljYXRlZCJ9.jNLynx_4nCpPv1fNkNFOzPQ-Y_vPxJAlDV8sp-590ZM", "vsn" => "1.0.0"}
realtime-realtime-1 | 2022-07-11 11:56:11.553 [info] JOINED realtime:* in 190ms
realtime-realtime-1 | Parameters: %{}
realtime-realtime-1 | 2022-07-11 11:56:11.686 [info] JOINED realtime:public in 131ms
realtime-realtime-1 | Parameters: %{}
realtime-realtime-1 | 2022-07-11 11:56:11.695 [info] JOINED realtime:public:users in 9ms
realtime-realtime-1 | Parameters: %{}
realtime-realtime-1 | 2022-07-11 11:56:15.476 [info] tzdata release in place is from a file last modified Wed, 21 Oct 2020 18:40:20 GMT. Release file on server was last modified Wed, 16 Mar 2022 13:36:02 GMT.
realtime-realtime-1 | 2022-07-11 11:56:17.533 [info] Tzdata has updated the release from 2020d to 2022a
realtime-realtime-1 | 2022-07-11 12:00:17.448 [error] %Postgrex.Error{connection_id: 184, message: nil, postgres: %{code: :undefined_function, file: "parse_func.c", hint: "No function matches the given name and argument types. You might need to add explicit type casts.", internal_position: "1", internal_query: "realtime.build_prepared_statement_sql('walrus_rls_stmt', entity_, columns)", line: "629", message: "function realtime.build_prepared_statement_sql(unknown, regclass, realtime.wal_column[]) does not exist", pg_code: "42883", routine: "ParseFuncOrColumn", severity: "ERROR", unknown: "ERROR", where: "PL/pgSQL function realtime.apply_rls(jsonb,integer) line 228 at EXECUTE"}, query: nil}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment