In my application, i write transactions to post gres schema prod.
In order to debug, I have using the psql command line client on OSX
My table the only fields I have to fill are the are message field (json blob) and and status field (text).
Here is what the schema looks like
Table "prod.suggestions"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
------------------+--------------------------+-----------+----------+--------------------+----------+--------------+-------------
id | uuid | | not null | uuid_generate_v4() | plain | |
message | jsonb | | not null | | extended | |
status | text | | not null | | extended | |
transaction_hash | text | | | | extended | |
created_at | timestamp with time zone | | | CURRENT_TIMESTAMP | plain | |
updated_at | timestamp with time zone | | | CURRENT_TIMESTAMP | plain | |
Indexes:
"suggestions_pkey" PRIMARY KEY, btree (id)
Triggers:
update_updated_at_on_prod_suggestions BEFORE UPDATE ON prod.suggestions FOR EACH ROW EXECUTE PROCEDURE update_updated_at()
here is the function the trigger executes:
create function update_updated_at()
returns trigger
as
$body$
begin
new.updated_at = current_timestamp;
return new;
end;
$body$
language plpgsql;
Here is query to write the message:
INSERT INTO prod.suggestions (message, status) VALUES ('{"name": "Paint house", "tags": ["Improvements", "Office"], "finished": true}' , 'rcvd');
It returns INSERT 0 1 which I assume is a sucesss.
however when i query the table, it doesnt return anything.
select * from prod.suggestions;
I will appreciate any pointers on this.
This had nothing to do with postgres. I have another workers thread that was deleting all the data from the table.
Related
An example of some tables with the column I want to change.
+--------------------------------------+------------------+------+
| ?column? | column_name | data_type |
|--------------------------------------+------------------+------|
| x.articles | article_id | bigint |
| x.supplier_articles | article_id | bigint |
| x.purchase_order_details | article_id | bigint |
| y.scheme_articles | article_id | integer |
....
There are some 50 tables that have the column.
I want to change the article_id column from a numeric data type to a textual data type. It is found across several tables. Is there anyway to update them all at once ? Information schema is readonly so I cannot do an update on it. Other than writing inidividual alter statements for all the tables, is there a better way to do it ?
I am a relatively new user of Postgres 13. Let me first tell you, that the Postgres database is hosted on AWS aurora. I have a user that owns a schema and I have a specific table that this user should only be able to SELECT and INSERT rows to this table and execute TRIGGERS.
I have REVOKED ALL on this table for this user and GRANTED SELECT, INSERT, TRIGGER ON TABLE TO USER. The INSERT, SELECT, and TRIGGER work as expected. However, when I execute a SQL UPDATE on that table it still lets me update a row in that table! I also forgot to tell you I REVOKED ALL and performed the same GRANTS to rds_superuser on this table since this user is referenced to rds_superuser.
Any help would be greatly appreciated!
Following are the results of \d:
Column | Type | Collation | Nullable | Default
-----------------------+--------------------------+-----------+----------+------------------------
id | uuid | | not null | uuid_generate_v4()
patient_medication_id | bigint | | not null |
raw_xml | character varying | | not null |
digital_signature | character varying | | not null |
create_date | timestamp with time zone | | not null | CURRENT_TIMESTAMP
created_by | character varying | | |
update_date | timestamp with time zone | | |
updated_by | character varying | | |
deleted_at | timestamp with time zone | | |
deleted_by | character varying | | |
status | character varying(1) | | | 'A'::character varying
message_type | character varying | | not null |
Indexes:
"rx_cryptographic_signature_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"rx_cryptographic_signature_fk" FOREIGN KEY (patient_medication_id) REFERENCES tryon.patient_medication(id)
Triggers:
audit_trigger_row AFTER INSERT ON tryon.rx_cryptographic_signature FOR EACH ROW EXECUTE FUNCTION td_audit.if_changed_fn('id', '{}')
audit_trigger_stm AFTER TRUNCATE ON tryon.rx_cryptographic_signature FOR EACH STATEMENT EXECUTE FUNCTION td_audit.if_changed_fn() tr_log_delete_attempt BEFORE DELETE ON tryon.rx_cryptographic_signature FOR EACH STATEMENT EXECUTE FUNCTION tryon.fn_log_update_delete_attempt()
tr_log_update_attempt BEFORE UPDATE ON tryon.rx_cryptographic_signature FOR EACH STATEMENT EXECUTE FUNCTION tryon.fn_log_update_delete_attempt()
Following are the results of \z:
Schema | Name | Type | Access privileges | Column privileges | Policies
--------+----------------------------+-------+---------------------------------------+-------------------+----------
tryon | rx_cryptographic_signature | table | TD_Administrator=art/TD_Administrator+| |
| | | td_administrator=art/TD_Administrator+| |
| | | rds_pgaudit=art/TD_Administrator +| |
| | | rds_superuser=art/TD_Administrator | |
(1 row)
Thanks so much for your help!!
I have a function below (is_organizer) that works, and lets me use this method as a computed field in Hasura. The function below (is_chapter_member) which is almost identical, doesn't work.
WORKS
CREATE OR REPLACE FUNCTION is_organizer(event_row events, hasura_session json)
RETURNS boolean AS $$
SELECT EXISTS (
SELECT 1
FROM event_organizers o
WHERE
o.user_id::text = hasura_session->>'x-hasura-user-id'
AND
(event_row.id = o.event_id OR event_row.event_template_id = o.event_template_id)
);
$$ LANGUAGE SQL STRICT IMMUTABLE;
BROKEN
CREATE OR REPLACE FUNCTION is_chapter_member(c chapters, hasura_session json)
RETURNS boolean AS $$
SELECT EXISTS (
SELECT 1
FROM chapter_members m
WHERE
m.user_id::text = hasura_session->>'x-hasura-user-id'
AND
c.chapter_id = m.chapter_id
);
$$ LANGUAGE SQL STRICT IMMUTABLE;
When attempting to add this function (not call it, just create it) Postgres gives me the following error:
ERROR: missing FROM-clause entry for table "c"
LINE 9: c.chapter_id = m.chapter_id
Why would a function param need a where clause? Table dumps below...
Table "public.chapters"
Column | Type | Collation | Nullable | Default
-----------------+--------------------------+-----------+----------+--------------------------------------
id | integer | | not null | nextval('chapters_id_seq'::regclass)
title | text | | not null |
slug | text | | not null |
description | jsonb | | |
avatar_url | text | | |
photo_url | text | | |
region | text | | |
maps_api_result | jsonb | | |
lat | numeric(11,8) | | |
lng | numeric(11,8) | | |
created_at | timestamp with time zone | | not null | now()
updated_at | timestamp with time zone | | not null | now()
deleted_at | timestamp with time zone | | |
Table "public.chapter_members"
Column | Type | Collation | Nullable | Default
------------+--------------------------+-----------+----------+---------
user_id | integer | | not null |
chapter_id | integer | | not null |
created_at | timestamp with time zone | | not null | now()
updated_at | timestamp with time zone | | not null | now()
Table "public.events"
Column | Type | Collation | Nullable | Default
-------------------+-----------------------------+-----------+----------+---------------------------------------------------
id | integer | | not null | nextval('events_id_seq'::regclass)
event_template_id | integer | | not null |
venue_id | integer | | |
starts_at | timestamp without time zone | | not null |
duration | interval | | not null |
title | text | | |
slug | text | | |
description | text | | |
photo_url | text | | |
created_at | timestamp without time zone | | not null | now()
updated_at | timestamp without time zone | | not null | now()
deleted_at | timestamp without time zone | | |
ends_at | timestamp without time zone | | | generated always as (starts_at + duration) stored
Table "public.event_organizers"
Column | Type | Collation | Nullable | Default
-------------------+---------+-----------+----------+----------------------------------------------
id | integer | | not null | nextval('event_organizers_id_seq'::regclass)
user_id | integer | | not null |
event_id | integer | | |
event_template_id | integer | | |
This turned out to be using an incorrect column name in the broken function. chapter_id should have just been id on the c argument. I took Richard's prompt and tried putting parens around the arg like (c).chapter_id. This then correctly told me that chapter_id doesn't exist, and allowed me to fix the issue.
Probably something dumb, but I just can't make it work.
I have this table:
Table "public.office"
Column | Type | Collation | Nullable | Default
-------------+--------------------------+-----------+----------+-------------------------------
id | integer | | not null | generated by default as identity
name | text | | not null |
url | text | | |
domain | text | | |
...
Triggers:
updated_save_domain_from_url AFTER UPDATE OF url ON office FOR EACH ROW EXECUTE PROCEDURE save_domain_from_url()
And this trigger function:
-- TRIGGER FUNCTION
CREATE OR REPLACE FUNCTION public.save_domain_from_url()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
new.domain := substring(new.url from '(?:.*://)?(?:www\.)?([^/]*)');
RETURN new;
END;
$function$
Example row:
id | name | url | domain
-----+---------------------------------+--------+--------
425 | Van Halewyck & Marco Architects | [NULL] | [NULL]
When I update the URL:
update office set url = 'http://vanhalewyck-marco.com/en' where id = 425;
The domain is still null, trigger did not work:
id | name | url | domain
-----+---------------------------------+---------------------------------+--------
425 | Van Halewyck & Marco Architects | http://vanhalewyck-marco.com/en | [NULL]
Any hints of what might be going on, please help!!
Thanks
You need to have the trigger defined as BEFORE trigger. AFTER triggers (as yours) cannot alter the new record as they are executed after the record is inserted.
Best regards,
Bjarni
I am new to Postgresql and working on a project which takes snapshot of relation.I want to retrive the first 2 column name and datatype from \d+ command in postgresql and then use this result to create a another table with only first 2 column
I am stuck on this . Can someone guide me on this ?
Column | Type | Modifiers | Storage | Stats target | Description
--------------+-----------------------------+------------------------------------------------------------+----------+--------------+-------------
i | integer | | plain | |
updated_time | timestamp without time zone | default '2000-01-01 00:00:00'::timestamp without time zone | plain | |
version | numeric | default '0'::numeric | main | |
is_updated | boolean | default false | plain | |
name | character varying(20) | | extended | |
I would just use plPgSql here, eg:
t=# do
$$
begin
execute format('create table so as select %s from pg_database',(select string_agg(column_name,',') from information_schema.columns where table_name = 'pg_database' and ordinal_position <=2));
end;
$$
;
DO
t=# \d so
Table "public.so"
Column | Type | Modifiers
---------+------+-----------
datname | name |
datdba | oid |
t=# \d pg_database
Table "pg_catalog.pg_database"
Column | Type | Modifiers
---------------+-----------+-----------
datname | name | not null
datdba | oid | not null
encoding | integer | not null
datcollate | name | not null
datctype | name | not null
datistemplate | boolean | not null
datallowconn | boolean | not null
datconnlimit | integer | not null
datlastsysoid | oid | not null
datfrozenxid | xid | not null
datminmxid | xid | not null
dattablespace | oid | not null
datacl | aclitem[] |
Indexes:
"pg_database_datname_index" UNIQUE, btree (datname), tablespace "pg_global"
"pg_database_oid_index" UNIQUE, btree (oid), tablespace "pg_global"
Tablespace: "pg_global"
update
the above is easily modifiable for other options if needed,eg:
t=# drop table so;
DROP TABLE
t=# do
$$
begin
execute format('create table so (%s) ',(select string_agg(column_name||' '||data_type||' '||case when is_nullable = 'NO' then 'NOT NULL' else '' end,',') from information_schema.columns where table_name = 'pg_database' and ordinal_position <=2));
end;
$$
;
DO
t=# \d so
Table "public.so"
Column | Type | Modifiers
---------+------+-----------
datname | name | not null
datdba | oid | not null
to include some modifiers...
update2
lastly if you want to use exact result from \d meta command - you can build you dinamic query from the one used by psql for \d:
-bash-4.2$ psql -E -c "\d pg_database"
********* QUERY **********
SELECT c.oid,
n.nspname,
...
and so forth