Query to foreign table impossible due to index on custom stored function value in host database - postgresql

I have a following situation.
In database A on server I, let's call it Host DB, there is a table, that has a following sample create script:
CREATE TABLE public.some_table (
id SERIAL PRIMARY KEY,
some_field TEXT
);
CREATE INDEX public.some_field_index
ON public.some_table USING btree
(my_custom_function(some_field));
As you can see, the index is created on a result of some custom, stored in database A, function my_custom_function.
Now I want to declare some_table as foreign table on other server, in database B. After creating the server, user mappings etc. I declare foreign table as:
CREATE FOREIGN TABLE public.some_table (
id SERIAL PRIMARY KEY,
some_field TEXT
)
SERVER host_server
OPTIONS (
schema_name 'public',
table_name 'some_table'
);
The table is created nicely, however I cannot query it. Instead I am getting following error:
ERROR: function my_custom_function(text) does not exist.
No function matches the given name and argument type.
You might need to add explcit type casts.
CONTEXT: Remote SQL command: SELECT id, some_field FROM public.some_table
SQL fuction my_custom_function during inlining.
I believe the problem is related to function my_custom_function not being declared on the server B, in the "guest" database. For some reasons i don't want to create this function. Is there any solution to overcome this problem?
Thanks for all your answers in advance.

Related

POSTGRESQL - Insert into foreign table triggered insertion into another remote table

I have a problem to update records into my foreign table.
It refers to a remote table which have a trigger to insert into another remote table (account_journals table).
I recreated same trigger and adding another foreign table which refers to the account_journals table, but i still have same error.
How i created my foreigns tables :
CREATE FOREIGN TABLE accounts (
...
)
SERVER fdw_server
OPTIONS (schema_name 'public', table_name 'remote_accounts');
CREATE FOREIGN TABLE
CREATE FOREIGN TABLE account_journals (
...
)
SERVER fdw_server
OPTIONS (schema_name 'public', table_name 'remote_account_journals');
CREATE FOREIGN TABLE
The trigger :
CREATE TRIGGER tg_account_journals AFTER INSERT OR DELETE OR UPDATE ON accounts FOR EACH row EXECUTE FUNCTION fill_account_journals();
fill_account_journals() function just insert record into account_journals.
When update record into accounts table :
new_database=# UPDATE accounts SET name = 'valou' WHERE id = 1;
ERROR: relation "remote_account_journals" does not exist
CONTEXT: PL/pgSQL function public.fill_remote_account_journals() line 8 at SQL statement
remote SQL command: UPDATE public.remote_accounts SET name = $2 WHERE ctid = $1 RETURNING id, name, ...
Any help is appreciated to solve my problem, thanks

postgres - how to test if peer of foreign table actually exists

I have two databases: let's call them primary (which holds actual data) and fdw (which contains foreign-data-wrapper of data in primary db).
I create simple table in primary db:
create schema myschema;
create table myschema.foo (id bigint, whatever text);
create table myschema.foov as select * from foo;
I create foreign table in fdw db accessing primary table through view:
create extension postgres_fdw;
create server remote_docker foreign data wrapper postgres_fdw options (host 'primary', dbname 'postgres', port '5432');
create schema remote_myschema;
create user mapping for current_user server remote_docker options (user 'postgres');
create foreign table remote_myschema.foo (id bigint, whatever text) server remote_docker options (schema_name 'myschema', table_name 'foov');
When executing select * from remote_myschema.foo query, everything works ok.
The problem: if I didn't create view in primary db, the create foreign table command in fdw db passes without error anyway. I am able to discover the nonexistency of view in primary db only at time of query execution on fdw db.
The question: is somehow possible to detect that foreign table is bound to nonexistent original? I compared pg_class data of foreign table in both cases and didn't find any difference nor anything in documentation. The only way I know at this moment is catching exception
do $$
declare
ex boolean;
begin
begin
execute 'select null from remote_myschema.foo';
ex := true;
exception when others then
ex := false;
end;
raise notice '%', ex::text;
end;
$$;
which is awful.
Thanks!
Catching the exception is the only way. Unless views are in the habit of suddenly disappearing at your site, you don't have to test it every time you use the foreign table. Testing once, right after you created it, is good enough.

How to convert a simple postgresql table to hypertable or timescale db table using created_at for indexing

The problem is that when I want to convert a simple Postgresql table to timescaledb table or hypertable using created_at table field for indexing then it will show this error. The table name is orders. Here cas_admin_db_new is the databse name.
I have tried all the possible way. which is bellow but the orders table doesn't convert into hypertable.
SELECT create_hypertable('orders','created_at', chunk_time_interval => 6040800000000);
ERROR: cannot create a unique index without the column "created_at" (used in partitioning)
SELECT create_hypertable('public.orders','created_at', chunk_time_interval => 6040800000000);
ERROR: cannot create a unique index without the column "created_at" (used in partitioning)
cas_admin_db_new=# SELECT create_hypertable('public.orders','created_at', chunk_time_interval => 6040800000000, created_default_indexes=>FALSE);
ERROR: function create_hypertable(unknown, unknown, chunk_time_interval => bigint, created_default_indexes => boolean) does not exist
cas_admin_db_new=# SELECT create_hypertable('"ORDER"','created_at', chunk_time_interval => 6040800000000);
ERROR: relation "ORDER" does not exist
LINE 1: SELECT create_hypertable('"ORDER"','created_at', chunk_time_...
Timescale person here. The issue is that your schema probably lists some other column as a primary key (or UNIQUE index).
TimescaleDB requires that any PK/unique index includes all partitioning keys, in your case, created_at.
That's because we do this heavy underlying partitioning, and don't want to build global lookup structures to ensure uniqueness outside of what we already use for partitioning.
More info:
https://docs.timescale.com/timescaledb/latest/how-to-guides/schema-management/indexing/##best-practices
You need to drop your current primary key on table and create new composite primary key like so:
ALTER TABLE table_name ADD PRIMARY KEY (id, created_at);
But there is problem: Unfortunately ActiveRecord doesn't support composite primary key.

Why doesn't knex create serial column in postgres?

I use knex to create a postgres table as following:
knex.schema.createTable('users', table => {
table.bigIncrements('user_id');
....
})
But after the table was created, the column user_id is a integer not the serial as expected.
The sql get by the pgAdmin is as following:
CREATE TABLE public.users
(
user_id bigint NOT NULL DEFAULT nextval('users_user_id_seq'::regclass),
....
)
And the consequence is that when I do insert statement, the user_id won't auto increment as expected.
Any gives?
====================
Currently I just changed to mysql connection, and the inserting works well. But if I changed the database back to postgresql, then inserting would fail due to the duplication of user_id. The code can be found here: https://github.com/buzz-buzz/buzz-service
serial and bigserial are not real types they are just shorthand for what pgAdmin is showing.
You will also find that a sequence has been created with the name users_user_id_seq when you look under sequences in pgAdmin.

Async foreign tables, foreign data wrapper

i am working on foreign data wrappers in postgres, using multicorn and using triggers to insert data in foreign tables, however i do not want the postgres to wait for response after trigger, just trigger inserts it and then forgets.
how can that be possible.
Actually i am using it for a foreign table
CREATE FOREIGN TABLE media_es (
id BIGINT,
title TEXT,
description TEXT,
tags TEXT,
query TEXT,
score NUMERIC
)
SERVER multicorn_es
OPTIONS (
host 'elasticsearch',
port '9200',
index 'test',
type 'media',
rowid_column 'id',
query_column 'query',
score_column 'score'
);
CREATE TRIGGER es_insert_media
AFTER INSERT
ON media
FOR EACH ROW
EXECUTE PROCEDURE index_media();
CREATE OR REPLACE FUNCTION index_media()
RETURNS trigger
AS $def$
BEGIN
INSERT INTO media_es
(
id,
title,
description,
tags
)
VALUES
(
NEW.id,
NEW.title,
NEW.description,
NEW.tags
)
;
RETURN NEW;
END;
$def$ LANGUAGE plpgsql;
postgres dblink extension allows async calls to remote server via dblink-send-query command.
not sure how it will work within trigger in terms of establishing multiple connections. caution should be taken here for resource leakage