patternsqlMajor
PostgreSQL: Pass table as argument in function
Viewed 0 times
postgresqlargumentpassfunctiontable
Problem
I am discovering
I can create table using this template with:
I have seen many options in the API, but I am a little lost. I would like to know if it is possible to assign this type to function
Let say that I have a
That is I would like to know if it is possible to create a
And that can be called like this:
I wonder that it is possible with PostgreSQL, and ask how to do so. Does anyone of you know?
Here is a MWE of what I am trying to do:
```
DROP TABLE IF EXISTS source;
DROP FUNCTION IF EXISTS process(dataset);
DROP TYPE dataset;
CREATE TYPE dataset AS (
id INTEGER
,t TIMESTAMP
,x FLOAT
);
CREATE TABLE source OF dataset;
ALTER TABLE source ADD PRIMARY KEY(Id);
INSERT INTO source VALUES
(1, '2016-01-01 00:00:00', 10.0)
,(2, '2016-01-01 00:30:00', 11.0)
,(3, '2016-01-01 01:00:00', 12.0)
,(4, '2016-01-01 01:30:00', 9.0)
;
CREATE OR REPLACE FUNCTION process(
_source dataset
)
RETURNS SETOF dataset
AS
$BODY$
SELECT * FROM source;
$BODY$
LANGUAGE SQL;
SELECT * FROM
TYPE in PostgreSQL. I have a TABLE TYPE that some table must respect (interface). For example:CREATE TYPE dataset AS(
ChannelId INTEGER
,GranulityIdIn INTEGER
,GranulityId INTEGER
,TimeValue TIMESTAMP
,FloatValue FLOAT
,Status BIGINT
,QualityCodeId INTEGER
,DataArray FLOAT[]
,DataCount BIGINT
,Performance FLOAT
,StepCount INTEGER
,TableRegClass regclass
,Tags TEXT[]
,WeightedMean FLOAT
,MeanData FLOAT
,StdData FLOAT
,MinData FLOAT
,MaxData FLOAT
,MedianData FLOAT
,Percentiles FLOAT[]
);I can create table using this template with:
CREATE TABLE test OF dataset;I have seen many options in the API, but I am a little lost. I would like to know if it is possible to assign this type to function
INPUT/OUTPUT parameters.Let say that I have a
FUNCTION called process that receives a sample of records from a dataset TABLE source, processes them and then returns a TABLE sink with the same TYPE.That is I would like to know if it is possible to create a
TYPE that behaves like this:CREATE FUNCTION process(
input dataset
) RETURNS dataset
AS ...And that can be called like this:
SELECT
*
FROM
source, process(input := source) AS sink;I wonder that it is possible with PostgreSQL, and ask how to do so. Does anyone of you know?
Here is a MWE of what I am trying to do:
```
DROP TABLE IF EXISTS source;
DROP FUNCTION IF EXISTS process(dataset);
DROP TYPE dataset;
CREATE TYPE dataset AS (
id INTEGER
,t TIMESTAMP
,x FLOAT
);
CREATE TABLE source OF dataset;
ALTER TABLE source ADD PRIMARY KEY(Id);
INSERT INTO source VALUES
(1, '2016-01-01 00:00:00', 10.0)
,(2, '2016-01-01 00:30:00', 11.0)
,(3, '2016-01-01 01:00:00', 12.0)
,(4, '2016-01-01 01:30:00', 9.0)
;
CREATE OR REPLACE FUNCTION process(
_source dataset
)
RETURNS SETOF dataset
AS
$BODY$
SELECT * FROM source;
$BODY$
LANGUAGE SQL;
SELECT * FROM
Solution
The parameter
But it would not work like this anyway. SQL only allows to parameterize values in DML statements. See:
Solution
You can still make it work using dynamic SQL with
See:
Or search for related questions and answers on site.
To make it work for any given table:
Detailed explanation:
_source in the MWE (minimal working example) is not referenced anywhere. The identifier source in the function body has no leading underscore and is interpreted as constant table name independently.But it would not work like this anyway. SQL only allows to parameterize values in DML statements. See:
- Error when setting n_distinct using a plpgsql variable
Solution
You can still make it work using dynamic SQL with
EXECUTE in a plpgsql function:CREATE TYPE dataset AS (id integer, t timestamp, x float);
CREATE TABLE source OF dataset (PRIMARY KEY(Id)); -- add constraints in same command
INSERT INTO source VALUES
(1, '2016-01-01 00:00:00', 10.0)
,(2, '2016-01-01 00:30:00', 11.0);
CREATE OR REPLACE FUNCTION process(_tbl regclass)
RETURNS SETOF dataset AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || _tbl;
END
$func$ LANGUAGE plpgsql;
SELECT * FROM process('source'); -- table name as string literalSee:
- Table name as a PostgreSQL function parameter
Or search for related questions and answers on site.
To make it work for any given table:
CREATE OR REPLACE FUNCTION process2(_tbl anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || pg_typeof(_tbl);
END
$func$ LANGUAGE plpgsql;
SELECT * FROM process2(NULL::source); -- note the call syntax!!Detailed explanation:
- Refactor a PL/pgSQL function to return the output of various SELECT queries
Code Snippets
CREATE TYPE dataset AS (id integer, t timestamp, x float);
CREATE TABLE source OF dataset (PRIMARY KEY(Id)); -- add constraints in same command
INSERT INTO source VALUES
(1, '2016-01-01 00:00:00', 10.0)
,(2, '2016-01-01 00:30:00', 11.0);
CREATE OR REPLACE FUNCTION process(_tbl regclass)
RETURNS SETOF dataset AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || _tbl;
END
$func$ LANGUAGE plpgsql;
SELECT * FROM process('source'); -- table name as string literalCREATE OR REPLACE FUNCTION process2(_tbl anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT * FROM ' || pg_typeof(_tbl);
END
$func$ LANGUAGE plpgsql;
SELECT * FROM process2(NULL::source); -- note the call syntax!!Context
StackExchange Database Administrators Q#141419, answer score: 21
Revisions (0)
No revisions yet.