crosstab function is not accessible to non-postgres users - postgresql

I've installed tablefuncs via create extension tablefuncs and can use crosstab from the postgres account. However, its not visible/usable to non-postgres users.
From postgres account:
\dx
List of installed extensions
Name | Version | Schema | Description
-----------+---------+------------+------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
tablefunc | 1.0 | public | functions that manipulate whole tables, including crosstab
(2 rows)
From non-postgres users:
abxdb=> set search_path to abx, public;
SET
abxdb=> \dx
List of installed extensions
Name | Version | Schema | Description
------------------+---------+------------+---------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
postgis | 2.0.7 | public | PostGIS geometry, geography, and raster spatial types and functions
postgis_topology | 2.0.7 | topology | PostGIS topology spatial types and functions
This is the example I'm trying to run:
CREATE TABLE example (
id int,
key text,
value text
);
INSERT INTO example VALUES
(123, 'firstName', 'John'),
(123, 'lastName', 'Doe');
SELECT *
FROM crosstab(
'SELECT *
FROM example
ORDER BY id ASC, key ASC;'
) AS ct(id INT, firstname TEXT, lastname TEXT);
I've tried creating the extension in the non-postgres account, but it must be created under postgres.

Related

What's the `IMAGE` type in Postgres?

By chance (mixing up the order of parameters), I set the column type to IMAGE in my postgres instance) and it worked (didn't get an error)! I have no idea what this type is, and it is not listed in the official table of types.
mydb=# CREATE TABLE tmp_image( image_column image );
CREATE TABLE
mydb=# \d tmp_image
Table "public.tmp_image"
Column | Type | Collation | Nullable | Default
--------------+-------+-----------+----------+---------
image_column | image | | |
Searching a bit, I found a postgres extension called pg_image, but I don't have any extensions installed:
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
I seem to be running 10.7 (psql (PostgreSQL) 10.7 (Ubuntu 10.7-0ubuntu0.18.04.1)).
You've created a composite type (by accident?). From the docs:
Whenever you create a table, a composite type is also automatically created, with the same name as the table, to represent the table's row type.
The same thing seems to apply to views even though I couldn't find this stated explicitely. Anyway check this out:
postgres=# CREATE TABLE test (id int, data text);
CREATE TABLE
postgres=# CREATE TABLE test2 (id int, field test); -- note the type of [field]
CREATE TABLE
postgres=# INSERT INTO test2 (id, field) VALUES (2, ROW(1, 'test'));
INSERT 0 1
postgres=# SELECT * FROM test2;
id | field
----+-------
2 | (1,test)
(1 row)
postgres=# SELECT (field).data FROM test2;
data
------
test
(1 row)
postgres=# SELECT * FROM test;
id
----
(0 rows)
Note how test becomes a part of test2. It is not a foreign reference.

Postgres Translate column value into schema prefix in a query

I have a database that uses postgresql schemas for multi-tenancy purposes. It has a table in the public schema called customers with an id and tenant column. The value for tenant is a string, and there's a corresponding postgresql schema with tables in it that match.
It looks like this:
# public.customers # first.users # second.users
| id | tenant | | id | name | | id | name |
|----|--------| |----|--------| |----|--------|
| 1 | first | | 1 | bob | | 1 | jen |
| 2 | second | | 2 | jess | | 2 | mike |
I'm wondering how I could make a single query to fetch values from a table in the schema, just given a customer id.
So if I have a customer_id of 1, how can I select * from first.users in a single query.
I'm guessing this might have to be a function written in pgpsql, but I don't have a lot of experience with that. Something like:
select * from tenant_table(1, 'users');
?
create or replace function f(_id int)
returns table (id int, name text) as $f$
declare _tenant text;
begin;
select tenant into _tenant
from public.customers
where id = _id;
return query execute format($e$
select *
from %I.users
$e$, _tenant);
end;
$f$ language plpgsql;
You cannot do that with a single query.
You'll have to use one query that selects the schema name, then construct a second query and run that.
Of course you can define a PL/pgSQL function that does both for you and executes the dynamic query with EXECUTE.

How do we get all columns which are the part of sortkey in Redshift

I need to get all columns, which are the part of sortkey in Redshift.
I tried get information using "select * from svv_table_info" but it have only the information of one column only. Can you let me know, how do I get all columns which are the part of Sortkey for a table.
Thanks,
Sanjeev
Thanks all for your help. I already tried "pg_table_def" table to get sortkey and distkey information but I have seen only pg_catalog and Public schema, I just go through the Amazon developer guide and found we need to add schema to search path using below commands:-
show search_path;
set search_path to '$user', 'public', 'NewSchema';
After adding the "NewSchema" in search path I can see sortkey and distkey information for this schema in pg_table_def
Thanks,
Sanjeev
Sanjeev,
A table called pg_table_def has information about the columns.
In the example below, I created a simple table with four columns and used 2 of these columns as my sort key.
As you can see in my query results the "sort key" field shows a number other than 0 if the column is part of a sort key.
dev=# drop table tb1;
DROP TABLE
dev=# create table tb1 (col1 integer, col2 integer, col3 integer, col4 integer) distkey(col1) sortkey(col2, col4);
CREATE TABLE
dev=# select * from pg_table_def where tablename = 'tb1';
schemaname | tablename | column | type | encoding | distkey | sortkey | notnull
------------+-----------+--------+---------+----------+---------+---------+---------
public | tb1 | col1 | integer | none | t | 0 | f
public | tb1 | col2 | integer | none | f | 1 | f
public | tb1 | col3 | integer | none | f | 0 | f
public | tb1 | col4 | integer | none | f | 2 | f
(4 rows)
What about:
select "column", type, encoding, distkey, sortkey, "notnull"
from pg_table_def
where tablename = 'YOURTABLE'
and sortkey <> 0;

See all indexes and appropriate columns for table

How to see all existed indexes for table? for example given table mytable, how to see his every index with appropriate columns?
Try this SQL
SELECT * FROM pg_indexes WHERE tablename = 'mytable';
In psql use the \d command:
postgres=> create table foo (id integer not null primary key, some_data varchar(20));
CREATE TABLE
postgres=> create index foo_data_idx on foo (some_data);
CREATE INDEX
postgres=> \d+ foo
Table "public.foo"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------+-----------+----------+--------------+------------
id | integer | not null | plain | |
some_data | character varying(20) | | extended | |
Indexes:
"foo_pkey" PRIMARY KEY, btree (id)
"foo_data_idx" btree (some_data)
Has OIDs: no
postgres=>
Other SQL tools have other means of displaying this information.

Why is PostgreSQL saying a constraint doesn't exist when I try to drop it?

I'm working with PostgreSQL 9.1.
In psql I'm using this query to discover what constraints I have in a certain DB...
SELECT
*
FROM
information_schema.constraint_table_usage
WHERE
constraint_table_usage.table_catalog = 'journal_app_development'
AND
constraint_table_usage.constraint_name NOT LIKE '%_pkey';
Output...
table_catalog | table_schema | table_name | constraint_catalog | constraint_schema | constraint_name
-------------------------+--------------+------------+-------------------------+-------------------+-----------------
journal_app_development | public | users | journal_app_development | public | fk_entry_user
journal_app_development | public | users | journal_app_development | public | fk_user_task
(2 rows)
But when I try to drop a constraint I get an error...
# ALTER TABLE users DROP CONSTRAINT "fk_entry_user";
ERROR: constraint "fk_entry_user" of relation "users" does not exist
Any idea what I'm doing wrong?
Background info / motivation
The reason I'm doing this is that I want to write a script (specifically a Rake task) that will drop constraints in the DB that aren't primary keys.
Try looking at the table:
information_schema.table_constraints
where the constraint_type column <> 'PRIMARY KEY'. I believe that should give you the other side of the relationship.
I believe you are trying to drop the constraint from the referenced table, not the one that owns it.