I'm using pgAdmin 4.23, PostgreSQL 12.3 for Windows
Looks like all functions are dumped into one "folder". I installed the uuid and tablefunc extensions and they get tossed in with my own user defined functions. At least the 10 uuid ones are all prefixed with "uuid_". The 11 tablefunc ones all start with "connectby", "crosstab"*, "normal_rand".
I did prefix my own functions so those at least grouped together. But as this thing grows and I add extensions, I'm concerned that maintenance will become more difficult. Is there some sort of sub-foldering option I am missing, or is naming convention the normal approach for organization? Looks like stored procs would work the same way.
Would also be nice to be able to filter the Functions based on the names. I see the Search Objects popup, but it isn't as useful as a filter.
To filter functions based on their names you can use this function:
CREATE OR REPLACE FUNCTION public.find_function(fname text DEFAULT NULL::text)
RETURNS TABLE(routine_name text, routine_schema text, return_type text)
LANGUAGE sql
AS $function$
select routine_name, routine_schema, data_type
from information_schema.routines
where specific_schema not in ('pg_catalog', 'information_schema')
and case when fname is null then true else routine_name ~* fname end
order by routine_name;
$function$;
Here is an example - find all functions that have "test" in their name:
select * from find_function('test');
+-----------------------------+----------------+-------------+
| routine_name | routine_schema | return_type |
+-----------------------------+----------------+-------------+
| clear_web_tests | datavato | void |
+-----------------------------+----------------+-------------+
| etl_generic_tests | webaccess | text |
+-----------------------------+----------------+-------------+
| fill_web_tests | datavato | void |
+-----------------------------+----------------+-------------+
| pan_arguments_test | helpers | jsonb |
+-----------------------------+----------------+-------------+
| test_bizday | public | boolean |
+-----------------------------+----------------+-------------+
| test_checkdigits | public | boolean |
+-----------------------------+----------------+-------------+
| test_jasper_dynamic_columns | scratch | record |
+-----------------------------+----------------+-------------+
I'm adding this here in case it helps for future searches...
Per #horse_with_no_name's suggestion above, and the official documentation I went with a separate schema for my third-party stuff. Here is a bit from conversation with the other db people in our company:
I didn't want third party extensions (like uuid-ossp for Guids)
installed in my public schema since that is where we keep all of our
user defined functions specific to that database. When I originally
installed the extension I put it into the public schema, then just
transferred it to a schema named extfunc. Then we have a table named
usr that references extfunc.uuid_generate_v4() in one of the column
constraints. Everything works as expected.
However, when I try to backup our Dev db and restore to QA, the
pg_dump and pg_restore tasks do not handle it properly. The restore
would error and not create the usr table. The extension was not being
properly restored to extfunc, which prevented the usr table from being
created.
The solution is to create the extension in the desired schema from the
start. Do not create it and try and move it to the destination
schema. Backup/restore now work as expected.
Related
is there any way to get the source code of the newly customized data type?
After sometime, I forgot the meaning of the newly created data type...
postgres=# \dT+ twoints
List of data types
Schema | Name | Internal name | Size | Elements | Owner | Access privileges | Description
--------+---------+---------------+-------+----------+----------+-------------------+-------------
public | twoints | twoints | tuple | | postgres | |
\dT+ seems don't give much info about the customized data type...
Also tried the pg_type catelog.
https://www.postgresql.org/docs/current/catalog-pg-type.html
typinput regproc (references pg_proc.oid)
Input conversion function (text format)
maybe typinput can help me, but I don't know.
through pgadmin4.
databases >> postgres >> schema >> Types >> twoints, right click CREATE Script
On development server I'd like to remove unused databases. To realize that I need to know if database is still used by someone or not.
Is there a way to get last access or modification date of given database, schema or table?
You can do it via checking last modification time of table's file.
In postgresql,every table correspond one or more os files,like this:
select relfilenode from pg_class where relname = 'test';
the relfilenode is the file name of table "test".Then you could find the file in the database's directory.
in my test environment:
cd /data/pgdata/base/18976
ls -l -t | head
the last command means listing all files ordered by last modification time.
There is no built-in way to do this - and all the approaches that check the file mtime described in other answers here are wrong. The only reliable option is to add triggers to every table that record a change to a single change-history table, which is horribly inefficient and can't be done retroactively.
If you only care about "database used" vs "database not used" you can potentially collect this information from the CSV-format database log files. Detecting "modified" vs "not modified" is a lot harder; consider SELECT writes_to_some_table(...).
If you don't need to detect old activity, you can use pg_stat_database, which records activity since the last stats reset. e.g.:
-[ RECORD 6 ]--+------------------------------
datid | 51160
datname | regress
numbackends | 0
xact_commit | 54224
xact_rollback | 157
blks_read | 2591
blks_hit | 1592931
tup_returned | 26658392
tup_fetched | 327541
tup_inserted | 1664
tup_updated | 1371
tup_deleted | 246
conflicts | 0
temp_files | 0
temp_bytes | 0
deadlocks | 0
blk_read_time | 0
blk_write_time | 0
stats_reset | 2013-12-13 18:51:26.650521+08
so I can see that there has been activity on this DB since the last stats reset. However, I don't know anything about what happened before the stats reset, so if I had a DB showing zero activity since a stats reset half an hour ago, I'd know nothing useful.
PostgreSQL 9.5 let us to track last modified commit.
Check track commit is on or off using the following query
show track_commit_timestamp;
If it return "ON" go to step 3 else modify postgresql.conf
cd /etc/postgresql/9.5/main/
vi postgresql.conf
Change
track_commit_timestamp = off
to
track_commit_timestamp = on
Restart the postgres / system
Repeat step 1.
Use the following query to track last commit
SELECT pg_xact_commit_timestamp(xmin), * FROM YOUR_TABLE_NAME;
SELECT pg_xact_commit_timestamp(xmin), * FROM YOUR_TABLE_NAME where COLUMN_NAME=VALUE;
My way to get the modification date of my tables:
Python Function
CREATE OR REPLACE FUNCTION py_get_file_modification_timestamp(afilename text)
RETURNS timestamp without time zone AS
$BODY$
import os
import datetime
return datetime.datetime.fromtimestamp(os.path.getmtime(afilename))
$BODY$
LANGUAGE plpythonu VOLATILE
COST 100;
SQL Query
SELECT
schemaname,
tablename,
py_get_file_modification_timestamp('*postgresql_data_dir*/*tablespace_folder*/'||relfilenode)
FROM
pg_class
INNER JOIN
pg_catalog.pg_tables ON (tablename = relname)
WHERE
schemaname = 'public'
I'm not sure if things like vacuum can mess this aproach, but in my tests it's a pretty acurrate way to get tables that are no longer used, at least, on INSERT/UPDATE operations.
I guess you should activate some log options. You can get information about logging on postgreSQL here.
I'm working on a marketplace platform, where I store user balances as a table of balance changes, along with a precalculated value in their user row. This allows me to check their balance easily, but still recalculate at specific intervals to ensure they stay in sync.
Here is an example of what the balance change table might look like:
| id | opening_balance | closing_balance | user_id |
|----|-----------------|-----------------|---------|
| 1 | 23.40 | 28.20 | 6 |
| 2 | 14.70 | 11.10 | 79 |
| 3 | 117.12 | 107.12 | 20 |
When a new row is inserted, I want to update the balance column on the user_id relation to the newly inserted closing_balance.
From what I've found online, I've got the following however it's for MySQL rather than Postgresql.
CREATE TRIGGER balance_update
AFTER INSERT ON balance_history
FOR EACH ROW
BEGIN
UPDATE users
SET balance = NEW.closing_balance
WHERE id = NEW.user_id;
END;
It looks like Postgresql requires you create a named procedure before creating a trigger? Not sure the best way to convert this.
Triggers in Postgres have a syntax a bit more complex than MySQL, because they execute procedures as the action. In this case, we can define a function which will perform the update you want as a result of the insert on the first table.
CREATE OR REPLACE FUNCTION your_proc()
RETURNS trigger AS
$$
BEGIN
UPDATE users
SET balance = NEW.closing_balance
WHERE id = NEW.user_id;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';
CREATE TRIGGER balance_update
AFTER INSERT ON balance_history
FOR EACH ROW
EXECUTE PROCEDURE your_proc();
I have a query that use array_agg with distinct as an argument and is not accepted on postgres 9.6.
I created this sample to illustrate the issue:
create table numbers (id integer primary key, name varchar(10));
insert into numbers values(1,'one');
insert into numbers values(2,'two');
postgres 9.4
select array_agg(distinct(id)) from numbers;
array_agg
-----------
{1,2}
postgres 9.6
ERROR: function array_agg(integer) is not unique
LINE 1: select array_agg(distinct(id)) from numbers;
^
HINT: Could not choose a best candidate function.
You might need to add explicit type casts.
What do I need to change in order to get this result on postgres 9.6?
Thanks.
This is what I get checking the functions:
nspname | proname | proargtypes
------------+-----------+---------------------
pg_catalog | array_agg | [0:0]={anyarray}
public | array_agg | [0:0]={anyelement}
pg_catalog | array_agg | [0:0]={anynonarray
Now, I found the issue thanks to the comment by pozs. I remove the public definition of the aggregated function and it worked.
The issue was just on the database that I was working on, as I found some people saying that the sample worked for them I created a new database an run the example. And then the only change there was the aggregate function definitions.
Now, I found the issue thanks to the comment by pozs. I remove the public definition of the aggregated function and it worked.
The issue was just on the database that I was working on, as I found some people saying that the sample worked for them I created a new database an run the example. And then the only change there was the aggregate function definitions.
So I drop the function public | array_agg | [0:0]={anyelement} and it worked.
Thanks a lot.
It works exactly like that as demonstrated by this dbfiddle on PostgreSQL 9.6.2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit.
When I do a \dt in psql I only get a listing of tables in the current schema (public by default).
How can I get a list of all tables in all schemas or a particular schema?
In all schemas:
=> \dt *.*
In a particular schema:
=> \dt public.*
It is possible to use regular expressions with some restrictions
\dt (public|s).(s|t)
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
public | s | table | cpn
public | t | table | cpn
s | t | table | cpn
Advanced users can use regular-expression notations such as character classes, for example [0-9] to match any digit. All regular expression special characters work as specified in Section 9.7.3, except for . which is taken as a separator as mentioned above, * which is translated to the regular-expression notation .*, ? which is translated to ., and $ which is matched literally. You can emulate these pattern characters at need by writing ? for ., (R+|) for R*, or (R|) for R?. $ is not needed as a regular-expression character since the pattern must match the whole name, unlike the usual interpretation of regular expressions (in other words, $ is automatically appended to your pattern). Write * at the beginning and/or end if you don't wish the pattern to be anchored. Note that within double quotes, all regular expression special characters lose their special meanings and are matched literally. Also, the regular expression special characters are matched literally in operator name patterns (i.e., the argument of \do).
You can select the tables from information_schema
SELECT * FROM information_schema.tables
WHERE table_schema = 'public'
Alternatively to information_schema it is possible to use pg_tables:
select * from pg_tables where schemaname='public';
For those coming across this in the future:
If you would like to see a list of relations for several schemas:
$psql mydatabase
mydatabase=# SET search_path TO public, usa; #schema examples
SET
mydatabase=# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+----------
public | counties | table | postgres
public | spatial_ref_sys | table | postgres
public | states | table | postgres
public | us_cities | table | postgres
usa | census2010 | table | postgres
If you are interested in listing all tables in a particular schema, I found this answer relevant :
SELECT table_schema||'.'||table_name AS full_rel_name
FROM information_schema.tables
WHERE table_schema = 'yourschemaname';