41. PostgreSQL: Catalog and tools
This chapter describes what a client sees of a MIRAJ instance in the PostgreSQL language: the pg_catalog catalog, information_schema and the SHOW statements, then the clients and drivers (psql, psycopg2, pgjdbc, Npgsql, ODBC, the miraj Python library), MIRAJ's tools on such an instance, and backup.
The examples use the ventes schema from getting started (tables client, article, commande, ligne_commande), completed with a view v_total_commande, a sequence seq_facture, a function ttc and a trigger trg_maj_stock.
41.1 Model: one database, one schema per MIRAJ database#
| PostgreSQL concept | In MIRAJ |
|---|---|
database (pg_database, current_database()) | a single one, miraj (OID 16384, UTF8 encoding) |
schema (pg_namespace) | a MIRAJ database; pg_catalog and information_schema are added to them |
current schema (current_schema, search_path) | the session's current database |
public | not a schema: in a name (public.client), an alias of the current database |
| object owner | root (OID 10) |
SELECT oid, nspname FROM pg_namespace ORDER BY nspname; oid | nspname
------------+--------------------
13183 | information_schema
689122271 | miraj
11 | pg_catalog
1505511691 | ventes
(4 lignes)The miraj schema is MIRAJ's system database: only root sees it. An ordinary account sees only the schemas on which it has a privilege (the app account from the getting started chapter sees information_schema, pg_catalog and ventes).
SELECT current_database(), current_schema, current_schemas(true), current_schemas(false); current_database() | current_schema | current_schemas(true) | current_schemas(false)
--------------------+----------------+-----------------------+------------------------
miraj | ventes | {pg_catalog,ventes} | {ventes}
(1 ligne)Object identifiers (OIDs). Base types and catalog tables keep PostgreSQL's OIDs (int4 23, text 25, numeric 1700, pg_class 1259). The objects you create receive an OID computed from their kind, schema and name: it does not change across restarts, but renaming an object changes its OID.
Name resolution. pg_catalog comes before any schema, as in PostgreSQL: SELECT * FROM pg_class reads the catalog table, without a prefix. A table in another schema is named schema.table.
Views on the catalog. A view can read the tables of pg_catalog and information_schema, alone, joined, through another view or through a WITH expression:
CREATE VIEW v_tables AS
SELECT n.nspname AS schema, c.relname AS nom
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' AND n.nspname = 'ventes';Its query is replayed on every read, on behalf of the account that reads it: it follows the catalog without delay (a table you create appears at once) and shows each account only what the catalog shows it. No result is kept, even for a view created by CREATE CACHED VIEW; REFRESH VIEW has no effect on it. A view on pg_authid or pg_shadow remains reserved for whoever administers accounts, at creation as at read time (42501).
Read-only. The catalog is rebuilt on every statement that reads it; nothing can be written to it:
INSERT INTO pg_class (relname) VALUES ('x');ERREUR 42501 : permission denied for schema pg_catalog41.2 The pg_catalog catalog#
Tables and views present#
The columns are those of PostgreSQL 16, in the same order and with the same types.
| Table or view | Content | |||
|---|---|---|---|---|
pg_namespace | the schemas visible to the account, pg_catalog, information_schema | |||
pg_database | the miraj database | |||
pg_class | tables (relkind = r), views (v), indexes (i), sequences (S), and the catalog tables | |||
pg_attribute, pg_attrdef | columns of tables and views (type, attnotnull, identity attidentity = d for a serial or BY DEFAULT, a for GENERATED ALWAYS, generated column), default values | |||
pg_index, pg_indexes | indexes: primary key <table>_pkey, uniqueness, secondary indexes (btree), full-text (gin), spatial (gist), vector (hnsw) | |||
pg_constraint | constraints p (primary key), u (uniqueness), f (foreign key), c (CHECK) | |||
pg_type, pg_enum, pg_range | base types and their arrays (92 types), one enumerated type per ENUM column; pg_range empty | |||
pg_proc, pg_language | functions (prokind = f) and procedures (p); languages internal, c, sql, plpgsql | |||
pg_trigger | triggers, under their PostgreSQL name | |||
pg_sequence, pg_sequences | sequences (CREATE SEQUENCE); pg_sequences presents them with their schema, owner and bounds | |||
pg_views, pg_tables, pg_matviews | usual views; pg_matviews empty | |||
pg_description | comments on tables and columns (COMMENT ON) | |||
pg_roles, pg_user, pg_authid, pg_shadow, pg_auth_members | one role per account, its attributes (rolsuper, rolcreatedb, rolcreaterole) and the granted roles; password always masked; pg_authid and pg_shadow reserved for whoever administers accounts (42501, permission denied for table pg_authid) | |||
pg_settings | parameters announced to clients and session variables (209 rows) | |||
pg_stat_activity | open sessions | |||
pg_am, pg_collation, pg_tablespace, pg_extension | access methods (heap, btree, hash, gist, gin, hnsw), collations default / C / POSIX, pg_default / pg_global, extension vector 0.8.0 | pg_inherits, pg_partitioned_table, pg_depend, pg_locks, pg_stat_user_tables, pg_shdescription, pg_policy, pg_publication, pg_publication_rel, pg_publication_namespace, pg_statistic_ext, pg_rewrite, pg_foreign_data_wrapper, pg_foreign_server, pg_foreign_table, pg_opclass, pg_event_trigger, pg_init_privs | present and empty, so that the queries of clients that join them run |
The catalog arrays (conkey, proargnames...) are rendered as arrays ({1,2}), indkey as int2vector (1 2).
Extensions. vector is the only row of pg_extension and does not need to be installed. CREATE EXTENSION [IF NOT EXISTS] name [WITH] [SCHEMA s] [VERSION v] [CASCADE] and DROP EXTENSION [IF EXISTS] name [, ...] are accepted with no effect for plpgsql, pgcrypto, uuid-ossp, unaccent, pg_trgm, fuzzystrmatch, btree_gin, btree_gist and vector, whose functions (gen_random_bytes, uuid_generate_v4, unaccent, similarity, levenshtein...) are always available (37. SQL functions): an installation script written for PostgreSQL runs unchanged.
Objects of a schema#
SELECT c.relname, c.relkind, c.relnatts, c.reltuples
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'ventes'
ORDER BY c.relkind, c.relname; relname | relkind | relnatts | reltuples
---------------------+---------+----------+-----------
article_pkey | i | 1 | 3.0
client_pkey | i | 1 | 3.0
code | i | 1 | 3.0
commande_pkey | i | 1 | 3.0
email | i | 1 | 3.0
idx_commande_date | i | 1 | 3.0
ligne_commande_pkey | i | 2 | 4.0
article | r | 5 | 3.0
client | r | 6 | 3.0
commande | r | 4 | 3.0
ligne_commande | r | 4 | 4.0
seq_facture | S | 3 | 1.0
v_total_commande | v | 0 | 0.0
(13 lignes)The names are MIRAJ's: the primary key is called <table>_pkey, a column UNIQUE constraint takes the name of its column (email, code), a foreign key is <table>_ibfk_<n>, an unnamed CHECK constraint is CONSTRAINT_<n>, numbered within its table (article and ligne_commande each have their own CONSTRAINT_1).
Columns of a table#
SELECT a.attnum, a.attname, format_type(a.atttypid, a.atttypmod) AS type,
a.attnotnull, a.attidentity, pg_get_expr(d.adbin, d.adrelid) AS defaut
FROM pg_attribute a
LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum
WHERE a.attrelid = 'client'::regclass AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum; attnum | attname | type | attnotnull | attidentity | defaut
--------+---------+-----------------------------+------------+-------------+-------------------
1 | id | integer | t | d |
2 | nom | character varying(80) | t | |
3 | email | character varying(120) | t | |
4 | ville | text | f | |
5 | actif | boolean | t | | true
6 | cree_le | timestamp without time zone | f | | CURRENT_TIMESTAMP
(6 lignes)In pg_attribute, a serial column appears as an identity column (attidentity = d), with no default value in pg_attrdef; a GENERATED ALWAYS AS IDENTITY column carries a. information_schema.columns, for its part, presents it as PostgreSQL does: nextval('client_id_seq'::regclass) (41.6).
Indexes and constraints#
SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'commande' ORDER BY indexname; indexname | indexdef
-------------------+---------------------------------------------------------------------------
commande_pkey | CREATE UNIQUE INDEX commande_pkey ON ventes.commande USING btree (id)
idx_commande_date | CREATE INDEX idx_commande_date ON ventes.commande USING btree (passee_le)
(2 lignes)SELECT conname, contype, conkey, confrelid::regclass AS cible, pg_get_constraintdef(oid) AS definition
FROM pg_constraint
WHERE conrelid = 'ligne_commande'::regclass
ORDER BY conname; conname | contype | conkey | cible | definition
-----------------------+---------+--------+----------+---------------------------------------------------------------------
CONSTRAINT_1 | c | | 0 | CHECK (("quantite" > 0))
ligne_commande_ibfk_1 | f | {1} | commande | FOREIGN KEY (commande_id) REFERENCES commande(id) ON DELETE CASCADE
ligne_commande_ibfk_2 | f | {2} | article | FOREIGN KEY (article_id) REFERENCES article(id)
ligne_commande_pkey | p | {1,2} | 0 | PRIMARY KEY (commande_id, article_id)
(4 lignes)For a constraint that is not a foreign key, confrelid::regclass returns 0.
Primary key columns of a table:
SELECT a.attname
FROM pg_class c
JOIN pg_index i ON i.indrelid = c.oid AND i.indisprimary
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY (i.indkey)
WHERE c.relname = 'ligne_commande'
ORDER BY a.attnum; attname
-------------
commande_id
article_id
(2 lignes)Tables that reference a table:
SELECT conrelid::regclass AS table_enfant, conname, pg_get_constraintdef(oid)
FROM pg_constraint
WHERE contype = 'f' AND confrelid = 'client'::regclass; table_enfant | conname | pg_get_constraintdef(oid)
--------------+-----------------+-----------------------------------------------
commande | commande_ibfk_1 | FOREIGN KEY (client_id) REFERENCES client(id)
(1 ligne)Views, sequences, routines, triggers#
SELECT pg_get_viewdef('v_total_commande'::regclass); select "o"."id", "o"."client_id", sum(("l"."quantite" * "l"."prix_unit")) as "montant" from "commande" as "o" join "ligne_commande" as "l" on ("l"."commande_id" = "o"."id") group by "o"."id","o"."client_id";The definition is the one MIRAJ keeps: the query is rewritten, identifiers always quoted. pg_get_viewdef returns it preceded by a space and ending with ;, as PostgreSQL does; pg_views.definition and information_schema.views.view_definition return the same text, without the space or the ;.
SELECT seqrelid::regclass AS sequence, seqstart, seqincrement, seqmin, seqmax, seqcache, seqcycle
FROM pg_sequence; sequence | seqstart | seqincrement | seqmin | seqmax | seqcache | seqcycle
-------------+----------+--------------+--------+---------------------+----------+----------
seq_facture | 1000 | 1 | 1 | 9223372036854775806 | 1000 | f
(1 ligne)SELECT p.proname, p.prokind, l.lanname, p.provolatile,
pg_get_function_arguments(p.oid) AS arguments, pg_get_function_result(p.oid) AS resultat
FROM pg_proc p
JOIN pg_language l ON l.oid = p.prolang
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'ventes'; proname | prokind | lanname | provolatile | arguments | resultat
-----------+---------+---------+-------------+--------------------------------------------------+---------------
maj_stock | f | plpgsql | v | | trigger
ttc | f | plpgsql | i | ht numeric(10,2), taux numeric(4,2) DEFAULT 0.19 | numeric(10,2)
(2 lignes)SELECT pg_get_functiondef('ttc'::regproc);CREATE OR REPLACE FUNCTION ventes.ttc(ht numeric(10,2), taux numeric(4,2) DEFAULT 0.19)
RETURNS numeric(10,2)
LANGUAGE plpgsql
IMMUTABLE
AS $function$
BEGIN
RETURN round(ht * (1 + taux), 2);
END;
$function$SELECT tgname, tgrelid::regclass AS table, tgfoid::regproc AS fonction, pg_get_triggerdef(oid) AS definition
FROM pg_trigger; tgname | table | fonction | definition
---------------+----------------+-----------+--------------------------------------------------------------------------------------------------------------
trg_maj_stock | ligne_commande | maj_stock | CREATE TRIGGER trg_maj_stock AFTER INSERT ON ventes.ligne_commande FOR EACH ROW EXECUTE FUNCTION maj_stock()
(1 ligne)Routines and triggers are described in chapter 40.
Comments#
COMMENT ON applies to a table or a column; IS NULL removes the comment. A column comment redefines the column: the table is rewritten.
COMMENT ON TABLE client IS 'Clients de la boutique';
COMMENT ON COLUMN client.email IS 'Adresse de contact, unique';
SELECT obj_description('client'::regclass, 'pg_class') AS de_table,
col_description('client'::regclass, 3) AS de_colonne; de_table | de_colonne
------------------------+----------------------------
Clients de la boutique | Adresse de contact, unique
(1 ligne)Roles#
SELECT rolname, rolsuper, rolcanlogin, rolpassword FROM pg_roles ORDER BY rolname; rolname | rolsuper | rolcanlogin | rolpassword
---------+----------+-------------+-------------
app | f | t | ********
root | t | t | ********
(2 lignes)One role per account name (without its host). The password is never returned: ******** in pg_roles and pg_user, NULL in pg_authid. rolsuper, rolcreatedb and rolcreaterole follow the account's global privileges, pg_auth_members the granted roles, and pg_has_role queries them (see 39.2 and 38.5). Detailed privileges are not in the catalog (relacl is NULL): SHOW GRANTS FOR account returns them (see 39).
Information functions#
| Functions | Result |
|---|---|
version() | PostgreSQL 16.4 (MIRAJ 1.0.0) on x86_64-windows, 64-bit (aarch64-macos, x86_64-linux... depending on the server's platform) |
current_database(), current_catalog | miraj |
current_schema, current_schemas(bool) | current schema; {pg_catalog,ventes} |
current_user, current_role, session_user, pg_get_userbyid(oid) | account name, without its host |
pg_backend_pid() | session number (the one in pg_stat_activity.pid and in KILL) |
pg_postmaster_start_time(), pg_conf_load_time() | time the server started, time its configuration was loaded |
inet_server_addr(), inet_client_addr() | addresses of the server and of the client of the connection (127.0.0.1) |
pg_reload_conf() | t |
txid_current(), pg_current_xact_id(), txid_current_if_assigned(), txid_current_snapshot() | number of the current transaction (NULL for txid_current_if_assigned() outside a write), snapshot (626841:626841:) |
pg_advisory_lock(n), pg_try_advisory_lock(n), pg_advisory_unlock(n), pg_advisory_xact_lock(n), pg_try_advisory_xact_lock(n) | advisory locks, session-level or transaction-level; the try forms return t or f |
pg_column_size(x), pg_input_is_valid(text, type) | size of a value in bytes (pg_column_size('abc'::text): 4); pg_input_is_valid('x', 'integer'): f |
pg_terminate_backend(pid [, timeout]), pg_cancel_backend(pid) | closes session pid, interrupts its running query: t; f with a warning if pid is unknown |
format_type(oid, typmod), pg_typeof(x) | character varying(80), numeric(10,2), timestamp without time zone... |
pg_get_indexdef(oid), pg_get_constraintdef(oid), pg_get_viewdef(oid), pg_get_expr(text, oid) | definitions, in the PostgreSQL language |
pg_get_functiondef(oid), pg_get_function_arguments(oid), pg_get_function_identity_arguments(oid), pg_get_function_result(oid), pg_get_triggerdef(oid) | routines and triggers (pg_get_function_identity_arguments: ht numeric(10,2), taux numeric(4,2), without default values) |
obj_description(oid [, catalog]), col_description(oid, n), shobj_description(oid, catalog) | comments |
to_regclass(name), to_regtype(name), to_regnamespace(name), to_regproc(name), to_regrole(name) | OID, or NULL if the name does not exist |
pg_table_is_visible(oid), pg_function_is_visible(oid), pg_type_is_visible(oid) | t for an object of the current schema or of pg_catalog |
pg_relation_filepath(relation) | path of the relation in PostgreSQL style (base/16384/1075441615) |
has_table_privilege([role,] table, privilege), has_column_privilege([role,] table, column, privilege), has_any_column_privilege(...), has_schema_privilege([role,] schema, privilege), has_function_privilege([role,] function, 'EXECUTE') | actual privileges of the session's account, or of another account for whoever administers accounts (see 39.5); an object the account does not see returns 42P01 / 3F000 / 42883; has_database_privilege, has_sequence_privilege, has_type_privilege: always t |
pg_has_role([account,] role, 'MEMBER' | 'USAGE' | 'SET') | whether the role is granted to the account (see 39.5); unknown role: 42704 |
pg_relation_size(relation), pg_total_relation_size(relation), pg_table_size(relation), pg_indexes_size(relation), pg_database_size(name), pg_size_pretty(n) | sizes in bytes; the relation is given by its OID or its name (pg_relation_size('client'), 'ventes.client'), an unknown name returns 42P01 (relation "absente" does not exist); pg_indexes_size returns the estimated size of the table's indexes, which pg_total_relation_size adds to the table's size (client: 456 + 276 = 732); pg_size_pretty(20480::bigint) returns 20 kB |
current_setting(name [, missing_ok]) | value of a parameter; unknown: 42704 (unrecognized configuration parameter "nexiste"), or NULL with true |
pg_encoding_to_char(n), quote_ident(t), quote_literal(t), quote_nullable(t) | UTF8; "Mon Nom", 'l''été', NULL |
pg_is_in_recovery() | f |
Name conversions:
| Syntax | Result |
|---|---|
'client'::regclass | OID of the table in the current schema ('ventes.client'::regclass for another schema); 42P01 (relation "absente" does not exist) if it does not exist |
c.oid::regclass, conrelid::regclass | name of the table |
'int4'::regtype::oid | 23; atttypid::regtype returns the name (integer, numeric) |
'ttc'::regproc, tgfoid::regproc | OID of a routine, its name |
41.3 information_schema and SHOW statements#
information_schema#
information_schema is MIRAJ's own, presented in the PostgreSQL language in the way PostgreSQL does: the catalog columns (table_catalog, constraint_catalog, catalog_name...) carry the name of the instance's PostgreSQL database, miraj, the one current_database() returns (the MIRAJ language reads def there, like the reference). Its usual tables answer portable queries, with a few differences to know about:
| View | Notes |
|---|---|
schemata | catalog_name is miraj; also lists miraj, performance_schema and sys |
tables | table_catalog = miraj; table_type: BASE TABLE, VIEW, SEQUENCE |
columns | data_type carries the standard name (integer, character varying, timestamp without time zone, boolean, numeric); a serial column is presented as in PostgreSQL: column_default = nextval('<table>_<column>_seq'::regclass), is_identity = NO; a GENERATED ... AS IDENTITY column carries is_identity = YES, identity_generation ALWAYS or BY DEFAULT and a NULL column_default; udt_name carries the type's internal name (int4, int8, varchar, bpchar, bool, timestamptz, float8...; <table>_<column>_enum for an enumerated type, like pg_type.typname), udt_schema its schema (pg_catalog, or the table's for an enumerated type), udt_catalog is miraj |
routines | data_type carries the standard name (trigger, void, record for these pseudo-types); type_udt_name the internal name of the result type, type_udt_schema is pg_catalog, type_udt_catalog miraj (NULL for a procedure) |
table_constraints | the primary key is called <table>_pkey there, as in pg_constraint; carries table_catalog |
constraint_column_usage | columns each constraint applies to: those of a primary key or UNIQUE, the referenced columns of a foreign key, those a CHECK cites; PostgreSQL-language view only (absent from an instance in the MIRAJ language, where a view that reads it stays readable) |
key_column_usage | also carries referenced_table_name and referenced_column_name for a foreign key |
referential_constraints | update_rule, delete_rule (NO ACTION, CASCADE...) |
check_constraints | check_clause is written in the PostgreSQL language, identifiers in double quotes (("prix" >= 0)) |
views | view_definition in the PostgreSQL language |
routines | data_type carries the standard name (integer, text, character varying...), trigger for a trigger function, void, record |
triggers | a trigger written in the PostgreSQL language carries its name there, one row per event, action_statement = EXECUTE FUNCTION f(...) and its WHEN condition in action_condition |
sequences | sequences created by CREATE SEQUENCE |
domains | view present, empty |
schema_privileges, table_privileges | granted privileges (grantee = 'app'@'%') |
The names of these views and their columns are written indifferently in lower case or upper case.
SELECT constraint_name, table_name, constraint_type
FROM information_schema.table_constraints
WHERE table_schema = 'ventes' AND table_name IN ('client', 'commande')
ORDER BY table_name, constraint_name; constraint_name | table_name | constraint_type
-----------------+------------+-----------------
client_pkey | client | PRIMARY KEY
email | client | UNIQUE
commande_ibfk_1 | commande | FOREIGN KEY
commande_pkey | commande | PRIMARY KEY
(4 lignes)SELECT constraint_name, table_name, column_name, referenced_table_name, referenced_column_name
FROM information_schema.key_column_usage
WHERE table_schema = 'ventes' AND referenced_table_name IS NOT NULL
ORDER BY table_name, constraint_name; constraint_name | table_name | column_name | referenced_table_name | referenced_column_name
-----------------------+----------------+-------------+-----------------------+------------------------
commande_ibfk_1 | commande | client_id | client | id
ligne_commande_ibfk_1 | ligne_commande | commande_id | commande | id
ligne_commande_ibfk_2 | ligne_commande | article_id | article | id
(3 lignes)For a tool written for PostgreSQL, prefer pg_catalog, which is more faithful; information_schema suits simple queries (list of tables, of columns).
SHOW statements#
SHOW name reads a parameter, as in PostgreSQL; SHOW ALL returns all parameters (name, setting, description).
SHOW server_version; -- 16.4
SHOW search_path; -- ventes
SHOW sql_mode; -- POSTGRESQL,STRICT_TRANS_TABLES
SHOW transaction_isolation; -- read committed
SHOW statement_timeout; -- 5minMIRAJ's SHOW statements remain available, as an extension:
| Statement | Returns |
|---|---|
SHOW DATABASES | the schemas (MIRAJ databases) |
SHOW TABLES, SHOW FULL TABLES | tables, views and sequences of the current schema, with their kind |
SHOW CREATE TABLE t, SHOW CREATE VIEW v, SHOW CREATE SEQUENCE s, SHOW CREATE FUNCTION f | the definition, written in the PostgreSQL language |
SHOW COLUMNS FROM t, DESCRIBE t, SHOW INDEX FROM t, SHOW TABLE STATUS | description in MIRAJ style: MIRAJ types (int(11), longtext, tinyint(1), datetime(6)), primary key PRIMARY |
SHOW TRIGGERS | MIRAJ columns; a trigger written in the PostgreSQL language carries its name there and, for Statement, EXECUTE FUNCTION f(...) (one row per event) |
SHOW PROCESSLIST | sessions (see 41.7) |
SHOW GRANTS FOR account | privileges of an account |
SHOW VARIABLES LIKE '...', SHOW STATUS LIKE '...' | server variables and counters |
SHOW CREATE TABLE commande;CREATE TABLE "commande" (
"id" integer GENERATED BY DEFAULT AS IDENTITY (START WITH 4) NOT NULL,
"client_id" integer NOT NULL,
"passee_le" date NOT NULL DEFAULT CURRENT_DATE,
"etat" character varying(12) NOT NULL DEFAULT 'ouverte'::character varying,
PRIMARY KEY ("id"),
CONSTRAINT "commande_ibfk_1" FOREIGN KEY ("client_id") REFERENCES "client" ("id")
);
CREATE INDEX "idx_commande_date" ON "commande" ("passee_le")START WITH gives the number the next row will receive: a script replayed elsewhere resumes the numbering where it left off.
EXPLAIN query returns MIRAJ's plan, in its own layout (columns id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra):
EXPLAIN SELECT * FROM client WHERE id = 1; id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
----+-------------+--------+--------+---------------+---------+---------+-------+------+-------
1 | SIMPLE | client | eq_ref | PRIMARY,email | PRIMARY | | const | 1 |
(1 ligne)41.4 psql#
$env:PGPASSWORD = "password"
psql -h 127.0.0.1 -p 7007 -U root -d ventes
psql "host=server.example port=7007 user=root dbname=ventes sslmode=require"The -d parameter (or dbname) names the current schema (see 32.2). The server works only in UTF-8: on Windows, use chcp 65001 or PGCLIENTENCODING=UTF8.
The description commands read pg_catalog:
| Command | Shows |
|---|---|
\l | the single miraj database |
\dn | the schemas, that is, the MIRAJ databases |
\dt, \dv, \di, \ds, \d | tables, views, indexes, sequences of the current schema; \dt ventes.* for another schema |
\d table, \d+ table | columns (PostgreSQL types, default values, identity), indexes, constraints, foreign keys, triggers |
\du | accounts |
\df, \df+, \sf function | routines, text of a function |
\dx | vector extension |
\dp | tables, without detailed privileges |
\x | expanded display |
\copy t from 'file.csv' with (format csv, header), \copy t to 'output.txt' | loads or writes a file on the client machine (see 35) |
These commands send ordinary queries on the catalog. The one behind \d without an argument (tables, views and sequences of the current schema) returns here:
Schema | Name | Type | Owner
--------+------------------+----------+-------
ventes | article | table | root
ventes | client | table | root
ventes | commande | table | root
ventes | ligne_commande | table | root
ventes | seq_facture | sequence | root
ventes | v_total_commande | view | root
(6 lignes)A query typed or passed with -c can contain several statements; each returns its result and its tag. Ctrl-C cancels the running query (57014). psql -f script.sql runs a script, for example a miraj-dump export (41.9).
Not supported: \gdesc. The catalog queries are those of psql 10 to 18; a version that changed their text may receive a syntax error on a \d command.
41.5 Drivers and libraries#
Any PostgreSQL driver connects to the server's port, with the name of a schema as the database. MIRAJ's ODBC driver and the miraj Python library also speak both languages.
| Driver | Connection |
|---|---|
| psycopg2 (Python) | psycopg2.connect(host=..., port=7007, user=..., password=..., dbname="ventes") |
| pgjdbc (Java) | jdbc:postgresql://server:7007/ventes |
| Npgsql (.NET) | Host=server;Port=7007;Username=...;Password=...;Database=ventes |
| MIRAJ ODBC Driver | DRIVER={MIRAJ ODBC Driver};SERVER=server;PORT=7007;UID=...;PWD=...;DATABASE=ventes |
miraj Python library | miraj.connect(host=..., port=7007, user=..., password=..., dbname="ventes") |
Parameters announced at connection: server_version = 16.4, server_encoding = client_encoding = UTF8, DateStyle = ISO, MDY, integer_datetimes = on, standard_conforming_strings = on, TimeZone = the server's time zone. Any other client_encoding is refused (0A000).
psycopg2#
import psycopg2, psycopg2.extras
conn = psycopg2.connect(host="127.0.0.1", port=7007, user="app",
password="secret123", dbname="ventes")
cur = conn.cursor()
cur.execute("SELECT code, prix, stock FROM article WHERE prix > %s ORDER BY id", (2,))
for code, prix, stock in cur:
print(code, prix, stock) # CAH-96 2.50 200 / CLA-A4 4.90 80
cur.execute("INSERT INTO client (nom, email) VALUES (%(nom)s, %(email)s) RETURNING id",
{"nom": "Nadia Haddad", "email": "[email protected]"})
identifiant = cur.fetchone()[0]
conn.commit()| Topic | Behavior |
|---|---|
| Parameters | %s and %(name)s, substituted by psycopg2; cursor.mogrify writes 'l''été', NULL, '2026-01-02'::date |
| Types received | int, str, bool, Decimal (numeric), float, date, time, datetime (with a time zone for a timestamptz), dict / list (json, jsonb), memoryview (bytea), str (uuid) |
| Types sent | psycopg2.extras.Json(...) for a jsonb column, psycopg2.Binary(...) for a bytea, Decimal, dates and times |
| Tag | cursor.statusmessage: SELECT 3, INSERT 0 1, UPDATE 2...; cursor.rowcount |
| Generated identifier | INSERT ... RETURNING id; cursor.lastrowid is 0 |
| Transactions | opened at the first statement; commit(), rollback(), autocommit, with conn:; set_session(isolation_level=..., readonly=True) (a write then receives 25006) |
| Errors | psycopg2 classes from the SQLSTATE: UndefinedTable (42P01), UniqueViolation (23505), InFailedSqlTransaction (25P02), QueryCanceled (57014)...; e.pgcode, e.diag.message_primary |
| Notices | RAISE NOTICE from a function: conn.notices (NOTICE: bonjour 42) |
| Batches | executemany, psycopg2.extras.execute_values, execute_batch |
| Named cursor | conn.cursor(name="grand"): server-side DECLARE ... CURSOR, read by fetchmany; inside a transaction |
| Dictionary cursors | RealDictCursor, DictCursor |
| Copies | copy_from, copy_to, copy_expert (text and CSV) |
| Cancellation | conn.cancel() from another thread: the query fails with 57014; so does SET statement_timeout TO 1000 |
| Asynchronous mode | psycopg2.connect(async_=1, ...) with wait_select |
Bulk load and export:
import io
donnees = io.StringIO("GOM-01\tGomme blanche\t0.80\t300\nREG-30\tRègle 30 cm\t1.90\t120\n")
cur.copy_from(donnees, "article", columns=("code", "libelle", "prix", "stock"))
sortie = io.StringIO()
cur.copy_expert("COPY (SELECT code, libelle, prix FROM article ORDER BY id) "
"TO STDOUT WITH (FORMAT csv, HEADER)", sortie)
print(sortie.getvalue())code,libelle,prix
STY-01,Stylo bille,1.30
CAH-96,Cahier 96 pages,2.50
CLA-A4,Classeur A4,4.90
GOM-01,Gomme blanche,0.80
REG-30,Règle 30 cm,1.90Good to know:
cursor.callproc("f", ...)calls a function: psycopg2 sendsSELECT * FROM f(...), which returns one row of one column. For a procedure, writecur.execute("CALL p(%s)", ...).- The connection's
options(options="-c statement_timeout=5000", forms-c name=valueand--name=value, a backslash before a space in the value) are applied before the first query, as so manySETs:SHOW statement_timeoutreturns5s, andRESET statement_timeoutas well asRESET ALLreturn to it. An unknown option, a refused value or a server startup parameter (shared_buffers...) refuses the connection (FATAL,42704,22023,55P02...), as PostgreSQL does. The other command-line options of the PostgreSQL server (-d,-S...) are refused (42601). - The parameters that a driver writes in the startup message itself (pgjdbc and Npgsql:
client_encoding,DateStyle,TimeZone,extra_float_digits,search_path,application_name...) are set the same way, as starting values of the session. There, an unknown name or a value the server cannot honor (client_encodingother than UTF8,DateStyleother than ISO, unknown time zone) is ignored without refusing the connection. - An
executecall that contains several queries returns only the result of the last one, as with PostgreSQL.
pgjdbc and Npgsql#
These drivers prepare their queries: they use the extended protocol (parameters $1, $2..., values in text or binary), which the server supports. Chapter 16 gives the details and the list of functions tried (16.10.4).
| Driver | Supported |
|---|---|
| pgjdbc 42.7 | typed PreparedStatement, server-side prepared statements, batches (executeBatch), setFetchSize, isolation levels, getGeneratedKeys (RETURNING), CopyManager in text and CSV, DatabaseMetaData (getSchemas, getTables, getColumns, getPrimaryKeys, getImportedKeys, getExportedKeys, getIndexInfo, getTypeInfo...), updatable ResultSet |
| Npgsql 10 | Open (types loaded from pg_type), typed parameterized commands, reused prepared command, transactions, NpgsqlBatch, cancellation, ExecuteReader on INSERT ... RETURNING, BeginTextImport / BeginTextExport, GetSchema (Tables, Columns, Indexes, ForeignKeys...) |
| DBeaver | goes through pgjdbc: navigator (schemas, tables, columns, keys, indexes) and row editing |
await using var conn = new NpgsqlConnection("Host=serveur;Port=7007;Username=app;Password=…;Database=ventes");
await conn.OpenAsync();
await using var cmd = new NpgsqlCommand("SELECT libelle, prix FROM article WHERE prix > $1", conn);
cmd.Parameters.Add(new NpgsqlParameter { Value = 2.0m, NpgsqlDbType = NpgsqlDbType.Numeric });Common limits: no binary COPY (Npgsql's BeginBinaryImport), no COPY in a prepared statement.
MIRAJ ODBC driver#
MIRAJ ODBC Driver (installation and data sources: chapter 29) recognizes the instance's language at connection time; PROTOCOL=postgresql in the string forces it.
import pyodbc
cn = pyodbc.connect("DRIVER={MIRAJ ODBC Driver};SERVER=127.0.0.1;PORT=7007;"
"UID=app;PWD=secret123;DATABASE=ventes")
cur = cn.cursor()
cur.execute("SELECT id, nom, actif FROM client WHERE ville = ?", "Alger")
print(cur.fetchall()) # [(1, 'Amel Kaci', True)]
cur.execute("INSERT INTO client (nom, email) VALUES (?, ?) RETURNING id", "Essai", "[email protected]")
print(cur.fetchone()[0])
cn.commit()| Area | On an instance in the PostgreSQL language |
|---|---|
| SQL | that of this manual; the ? markers are bound as parameters; ODBC escape sequences are translated ({fn UCASE('abc')}, {d '2026-10-11'}, {fn CONVERT('12', SQL_INTEGER)}) |
SQLGetInfo | SQL_DBMS_NAME = PostgreSQL, SQL_DBMS_VER = 16.04.0000, identifier quote ", SQL_SCHEMA_TERM = schema, SQL_DATABASE_NAME = miraj |
| Catalog | SQLTables: TABLE_CAT = miraj, TABLE_SCHEM = the schema (ventes), types TABLE, VIEW, SEQUENCE; SQLColumns: types named int4, varchar, text, numeric...; SQLPrimaryKeys (key named <table>_pkey), SQLForeignKeys, SQLStatistics |
| Types | bool returned as a boolean, numeric as an exact decimal; SQLGetTypeInfo: text, json, jsonb, varchar, bpchar, uuid, bool, int8, bytea, numeric, int4, int2, float4, float8, date, time, timestamp, timestamptz |
| Results | several statements in one text: one result per statement (SQLMoreResults, cursor.nextset()) |
| Errors | PostgreSQL SQLSTATE (42P01, 23505...), native code 0 |
| Unknown database | DATABASE=inconnue: connection refused, 3D000 |
| TLS | SSLMODE=required on a server without a certificate: 08001 ("TLS exigé, mais le serveur ne le propose pas") |
| Generated identifier | INSERT ... RETURNING (the protocol does not transmit a last identifier) |
COPY is not available through ODBC. The driver's other limits are in 29.6. A third-party PostgreSQL driver (psqlODBC) also connects to such an instance.
miraj Python library#
The miraj library (27.12) offers psycopg2's DB-API interface to both languages: the same application connects to a MIRAJ or a PostgreSQL instance without changing API.
import miraj
conn = miraj.connect(host="127.0.0.1", port=7007, user="app", password="secret123",
dbname="ventes", protocol="postgresql")
cur = conn.cursor()
cur.execute("SELECT libelle, prix FROM article WHERE prix > %s", (2,))protocol:auto(default, language recognized at connection),mirajorpostgresql.dbnamenames the schema; an unknown schema is refused.- The
%sbecome the parameters$1,$2... of a prepared statement kept per connection and reused (executemanyprepares once). statusmessagecarries the server's tag;lastrowidisNone: useINSERT ... RETURNING.copy_from,copy_to,copy_expertandinsert_rowsgo throughCOPY.- Errors: PostgreSQL SQLSTATE (
e.sqlstate,e.pgcode); notices inconnection.notices. - No named cursor (
cursor(name=...):NotSupportedError): the result is read entirely at execution.
41.6 Common catalog queries#
Tables of a schema, with their size and comment:
SELECT n.nspname AS schema, c.relname AS table,
pg_size_pretty(pg_total_relation_size(c.oid)) AS taille,
obj_description(c.oid, 'pg_class') AS commentaire
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'miraj')
ORDER BY 1, 2; schema | table | taille | commentaire
--------+----------------+-----------+------------------------
ventes | article | 589 bytes |
ventes | client | 732 bytes | Clients de la boutique
ventes | commande | 344 bytes |
ventes | ligne_commande | 176 bytes |
(4 lignes)The sizes are those of the in-memory data, indexes included, not those of the files.
Existence of a table, with no error if it is missing:
SELECT to_regclass('client') IS NOT NULL AS client, to_regclass('absente') IS NOT NULL AS absente; client | absente
--------+---------
t | f
(1 ligne)Columns of a table through information_schema:
SELECT column_name, data_type, is_nullable, column_default, udt_name, is_identity
FROM information_schema.columns
WHERE table_schema = 'ventes' AND table_name = 'client'
ORDER BY ordinal_position; column_name | data_type | is_nullable | column_default | udt_name | is_identity
-------------+-----------------------------+-------------+------------------------------------+-----------+-------------
id | integer | NO | nextval('client_id_seq'::regclass) | int4 | NO
nom | character varying | NO | | varchar | NO
email | character varying | NO | | varchar | NO
ville | text | YES | | text | NO
actif | boolean | NO | true | bool | NO
cree_le | timestamp without time zone | YES | now() | timestamp | NO
(6 lignes)Types known to the server:
SELECT typname, oid, typcategory FROM pg_type
WHERE typname IN ('bool', 'int4', 'numeric', 'text', 'timestamptz', 'jsonb', 'uuid', 'vector')
ORDER BY typname; typname | oid | typcategory
-------------+-------+-------------
bool | 16 | B
int4 | 23 | N
jsonb | 3802 | U
numeric | 1700 | N
text | 25 | S
timestamptz | 1184 | D
uuid | 2950 | U
vector | 16385 | U
(8 lignes)41.7 Sessions and parameters#
SELECT pid, usename, datname, client_addr, state, query FROM pg_stat_activity ORDER BY pid; pid | usename | datname | client_addr | state | query
-----+---------+---------+-------------+--------+------------------------------------------------------------------------------------
1 | root | miraj | localhost | idle |
28 | root | miraj | localhost | active | SELECT pid, usename, datname, client_addr, state, query FROM pg_stat_activity ORDER BY pid
(2 lignes)pg_stat_activity takes over the sessions of SHOW PROCESSLIST. An ordinary account sees only its own sessions there. application_name is the one the session gave at connection or through SET; backend_start is not filled in.
A session is closed by pg_terminate_backend(pid), or by MIRAJ's KILL statement, with its pid; pg_cancel_backend(pid) and KILL QUERY pid interrupt only the running query (57014). The closed session receives the fatal error 57P01 (terminating connection due to administrator command) before its connection ends (see chapter 38).
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid <> pg_backend_pid() AND state = 'idle'; pg_terminate_backend
----------------------
t
t
(2 lignes)KILL 53 likewise closes session 53 and returns the tag KILL.
Both functions return t; for an unknown pid, f with the warning PID 99999 is not a PostgreSQL backend process (KILL answers 42704, Unknown thread id: 99999). An account closes only its own sessions, unless it has the administration privilege (PROCESS): 42501, permission denied to terminate process (You are not owner of thread 1 for KILL).
Parameters:
SELECT name, setting FROM pg_settings
WHERE name IN ('server_version', 'server_version_num', 'client_encoding', 'DateStyle', 'TimeZone',
'max_connections', 'password_encryption', 'search_path', 'transaction_isolation',
'statement_timeout')
ORDER BY name; name | setting
-----------------------+----------------
DateStyle | ISO, MDY
TimeZone | Etc/GMT-1
client_encoding | UTF8
max_connections | 151
password_encryption | scram-sha-256
search_path | ventes
server_version | 16.4
server_version_num | 160004
statement_timeout | 5min
transaction_isolation | read committed
(10 lignes)pg_settings brings together the parameters that PostgreSQL announces to clients and MIRAJ's session variables (autocommit, lock_wait_timeout...). As in PostgreSQL, its texts are compared and sorted byte by byte: names with capitals (DateStyle, TimeZone) come first, and name = 'datestyle' finds nothing. statement_timeout defaults to the maximum statement duration set on the server (5 minutes). current_setting('name') reads a value; settings are changed with SET (see 38).
41.8 MIRAJ tools#
MIRAJ's tools recognize the instance's language at connection time and speak that language to it. The --protocol auto | miraj | postgresql option (default auto) forces it; the connection options are the same in both languages (--host, --port, --user, --password, variable MIRAJ_PASSWORD, --ssl, --ssl-ca, --ssl-insecure, --no-ssl).
| Tool | On an instance in the PostgreSQL language |
|---|---|
miraj-cli | SQL console: statements and files in the PostgreSQL language, prompt schema=> |
miraj-backup | hot physical backup and restore (41.9) |
miraj-dump | export to a SQL script written in the PostgreSQL language (41.9) |
miraj-migrate | migration to MIRAJ: definitions rewritten in the PostgreSQL language, rows loaded by COPY, routines translated to PL/pgSQL (chapter 18) |
| Miraj Server Manager | monitoring and settings; shows the instance's language (chapter 22) |
miraj-proxy | relays PostgreSQL connections unchanged (chapter 23) |
miraj-cli#
$env:MIRAJ_PASSWORD = "password"
miraj-cli.exe --port 7007 -d ventesOK, 0 ligne(s) affectée(s)
MIRAJ 1.0.0 - connecté (langage PostgreSQL) - tapez \help pour l'aide, \q pour quitter.
ventes=> SELECT code, prix FROM article ORDER BY id LIMIT 2;
+--------+------+
| code | prix |
+--------+------+
| STY-01 | 1.30 |
| CAH-96 | 2.50 |
+--------+------+
2 ligne(s)
ventes=> SELECT 1/0;
ERREUR 22012 : division by zero| Use | Command |
|---|---|
| interactive console | miraj-cli --port 7007 -d ventes |
| one or more statements | miraj-cli --port 7007 -d ventes -e "SELECT 1 AS a; SELECT 2 AS b;" |
| a script | miraj-cli --port 7007 script.sql: statements run one by one, stopping at the first error (exit code 1) |
| result as JSON | --json: [ {"code": "STY-01", "prix": 1.30} ], followed by 1 ligne(s) |
- With
-d, the console first sets the current schema; the lineOK, 0 ligne(s) affectée(s)that precedes the banner (or the first result of-e) is its report. - Errors are displayed with their SQLSTATE (
ERREUR 42P01 : relation "absente" does not exist). - With
-eand several statements, the results of those that precede an error are displayed, then the error; the following ones are not run. - A script is split according to PostgreSQL's lexical rules: standard strings (
'l''été'),E'...',$$...$$. \llists the schemas (SHOW DATABASES),\dthe tables of the current schema (SHOW TABLES),\d tabledescribes a table in MIRAJ style (DESCRIBE: typesint(11),longtext...). For a description in PostgreSQL types, querypg_attribute(41.2) or useSHOW CREATE TABLE.- Ctrl-C interrupts the running statement (a procedure loop, a long query) and returns to the prompt.
- Exit code 2: connection impossible (wrong password:
connexion à [email protected]:7007 impossible : erreur SQL 28P01 : Access denied for user 'root'@'localhost' (using password: YES)). - With
--protocol mirajon a PostgreSQL instance, the connection fails after a wait (server disconnected): leaveauto.
The rest of the console (history, \timing, source) is described in chapter 26.
41.9 Backup and restore#
Two methods, the same as in the MIRAJ language (chapter 19):
| Method | Nature | Tool |
|---|---|---|
| hot physical copy | schema files, immediate restore | BACKUP DATABASE / RESTORE DATABASE, miraj-backup |
| SQL export | script in the PostgreSQL language, readable and portable | miraj-dump |
BACKUP DATABASE and RESTORE DATABASE#
These statements are MIRAJ extensions, available in the PostgreSQL language. The server must be started with a backup folder (--backup-dir E:\sauvegardes, or <backup_dir> in miraj_config.xml); the folder named in the statement is relative to it.
BACKUP DATABASE ventes TO 'sauv1'; Database | Directory | Files | Bytes | End_lsn
----------+----------------------+-------+-------+---------
ventes | E:\sauvegardes\sauv1 | 9 | 7247 | 1464
(1 ligne)RESTORE DATABASE ventes_copie FROM 'sauv1';WARNING: base ventes restaurée sous le nom ventes_copie : les références qualifiées par l'ancien nom (vues, routines, clés étrangères) le gardent
Database | Directory | Files | Bytes | End_lsn
--------------+----------------------+-------+-------+---------
ventes_copie | E:\sauvegardes\sauv1 | 9 | 7247 | 1464
(1 ligne)The restored schema is usable at once (SELECT count(*) FROM ventes_copie.client;) and appears in pg_namespace. The backup does not block writes.
Without --backup-dir, the statement is refused (XX000, the server is running without the --backup-dir option so it cannot execute this statement); so is a path outside that folder (XX000, The server is running with the --backup-dir option so it cannot execute this statement).
miraj-backup#
$env:MIRAJ_PASSWORD = "password"
miraj-backup backup --db ventes --to sauv2 --port 7007
miraj-backup restore --from sauv2 --db ventes_copie --replace --port 7007
miraj-backup verify --from E:\sauvegardes\sauv2
miraj-backup list --from E:\sauvegardes\sauv2ventes : 9 fichier(s), 7.1 Ko, position 1464 → E:\sauvegardes\sauv2
ventes_copie : 9 fichier(s), 7.1 Ko, position 1464 → E:\sauvegardes\sauv2
Sauvegarde valide : base ventes, 9 fichier(s), 7.1 Ko, position 1464backup and restore send BACKUP / RESTORE to the server (the folder is the server's, relative to its --backup-dir); --all backs up all schemas, --replace replaces an existing schema. verify and list read a local folder. The account must have the BACKUP_ADMIN privilege. A physical copy does not contain the accounts: keep them with miraj-dump --users.
miraj-dump#
miraj-dump --db ventes --users -r ventes.sql --port 7007
miraj-dump restore ventes.sql --port 7008
psql -h 127.0.0.1 -p 7008 -U root -d miraj -v ON_ERROR_STOP=1 -f ventes.sqlOn an instance in the PostgreSQL language, the script is written in that language and is reloaded with miraj-dump restore, miraj-cli or psql -f:
- tables as
SHOW CREATE TABLEreturns them, rows as multi-rowINSERT(quoted identifiers, standard strings, booleanstrue/false,byteaas'\x...'::bytea); - sequences, views, routines and triggers in PL/pgSQL (
CREATE OR REPLACE FUNCTION ... AS $function$...$function$), withoutDELIMITER; - reading takes place in a single transaction: the script reflects a single instant, without blocking the other sessions;
--usersadds the accounts and their privileges. A reloaded account connects with a clear-text password, over TLS or on the loopback, until its password is redefined (ALTER USER ... IDENTIFIED BY ...); such a script is a sensitive file, to be protected like a password file;- an export follows the language of the instance it was read from: one from an instance in the MIRAJ language does not reload into an instance in the PostgreSQL language, nor the reverse.
The export options (--tables, --no-data, --no-routines...) are described in 19.3.
41.10 Not supported and differences#
| Topic | On a MIRAJ instance |
|---|---|
| Missing catalog views | pg_stat_database, pg_stat_all_tables, pg_statio_user_tables, pg_stats, pg_prepared_statements, pg_cursors, pg_available_extensions, pg_timezone_names, pg_operator: 42P01 |
| Tables present but empty | pg_locks, pg_stat_user_tables, pg_depend, pg_inherits... (41.2): no locks or access statistics through them |
| Missing functions | inet_server_port, pg_current_wal_lsn: 42883 |
| Size functions | in-memory sizes; pg_indexes_size is an estimate (average key width per live row) |
'name'::regclass written alone | returns the OID (a number); oid::regclass returns the name |
confrelid::regclass of a constraint without a target table | 0 (PostgreSQL: -) |
| Privileges | relacl, attacl, nspacl NULL; has_table_privilege, has_column_privilege, has_any_column_privilege and has_schema_privilege return the actual privileges (9.5), the other has_*_privilege always t; pg_shadow and pg_authid reserved for whoever administers accounts, password always NULL |
pg_stat_activity | backend_start not filled in; client_addr as text (localhost); an open, idle transaction stays idle |
txid_current() | positive number, the same throughout the transaction, but specific to MIRAJ: neither increasing from one transaction to the next, nor comparable with those of PostgreSQL |
pg_settings | columns short_desc, unit empty for MIRAJ variables; the application_name row follows the value given at connection or through SET |
COMMENT ON | tables and columns only; COMMENT ON VIEW, FUNCTION, SCHEMA...: 0A000 |
CREATE EXTENSION, VACUUM | VACUUM: syntax error 42601; ANALYZE: 0A000; CREATE EXTENSION of an extension other than those in 41.2 (postgis...): 0A000. The vector extension is always present; CREATE EXTENSION vector is accepted with no effect |
information_schema | MIRAJ's own: MIRAJ-specific columns (column_type, column_key, extra...); the columns added for PostgreSQL (udt_name, udt_schema, type_udt_name, table_constraints.table_catalog) also hold through a view |
EXPLAIN | MIRAJ plan, in its own layout |
| Constraint names | MIRAJ's (<table>_pkey, <table>_ibfk_<n>, CONSTRAINT_<n>, column name for a column UNIQUE) |
| Object OIDs | computed from the name: stable, but changed by a rename |
pg_get_viewdef, CHECK | identifiers always quoted; rewritten query |
| psql | \gdesc refused |
| psycopg2 | callproc of a procedure: 42883 (write CALL); client_encoding other than UTF-8: 0A000; lastrowid = 0 |
| ODBC | no COPY |
LISTEN / NOTIFY | accepted, but the client receives no asynchronous notification: see 38 |
DROP INDEX a, b | 0A000: one index per statement |
The condensed list of what the catalog contains is in 30.9.