The following Statement show error
EXECUTE quote_ident('Calculate' || calc_type_row."Name") || '($1,$2)' USING calc_type_row."IntervalTypeId",'Meter';
Name, IntervalTypeId are column in a table.
The statement EXECUTE is expecting valid SQL statement - in this case SELECT statement. So you are missing SELECT keyword:
EXECUTE format ('SELECT %I($1, $2)', 'Calculate' || calc_type."Name") USING ...
Related
I have this query for a function in postgresql
EXECUTE FORMAT('SELECT * FROM riesgo.%I WHERE codigo = %L', TG_TABLE_NAME, NEW.codigo) INTO _colvar;
IF EXISTS _colvar THEN
UPDATE riesgo.ro_agresion SET
(nombre,creado_por,valor,activo) =
(NEW.nombre,NEW.creado_por,NEW.valor,NEW.activo)
WHERE codigo = NEW.codigo;
ELSE
RETURN NEW;
END IF;
RETURN NULL;
and I'm getting this
ERROR: column "exists" does not exist
LINE 1: SELECT EXISTS _colvar
The explanation for the confusing error can be found in the manual for pl/pgsql Expressions, which explains:
When you write a PL/pgSQL statement IF expression THEN ... PL/pgSQL will evaluate the expression by feeding a query like SELECT expression to the main SQL engine
So in your case, the expression is being translated to SELECT EXISTS _colvar, which looks to the query parser like a column named "EXISTS" being given an alias _colvar".
To fix it, you need something that would be valid in a select list. For instance:
IF _colvar IS NOT NULL ...
I'm struggling with a stored procedure which heavily uses dynamic queries. Among others I need to store maximum value of an existing column into a variable.
Postgres documents state "if you want to use dynamically determined table or column names, you must insert them into the command string textually". Based on that I've come up with following statement:
EXECUTE 'SELECT MAX(' || pkColumn::regclass || ') FROM ' ||
tableName::regclass INTO maxValue;
Table name seems to be OK, column name triggers error.
What am I doing wrong ?
Pavel
EXECUTE 'SELECT MAX(' || pkColumn ||'::regclass) FROM ' || ...
::regclass is a cast done inside query. You can also skip it, or put " - which in PG works the same. So please try one of:
EXECUTE 'SELECT MAX(' || pkColumn || ') FROM ' || ...
or
EXECUTE 'SELECT MAX("' || pkColumn || '") FROM ' || ...
All tree should work. If not - just let me know. In that case it is my fault, postgresql simply works.
There is no reason to cast parameters as they are just identifiers. For better control and readability use the function format(), e.g.:
declare
pkcolumn text = 'my_column';
tablename text = 'my_table';
...
execute format('select max(%I) from %I', pkcolumn, tablename)
into maxvalue;
I have a PL/pgSQL function that takes table name as dynamic parameter. As I am updating an existing query to take table name as dynamic parameter, this is what I have as my function:
DECLARE rec RECORD;
BEGIN
EXECUTE 'insert into stat_300_8_0(ts, target, data)
select distinct timestamp-(timestamp%3600) as wide_row_ts,
target, array[]::real[] as data
from ' || temp_table_name || ' as temp
where class_id=8
and subclass_id=0
and not exists (select ts from stat_300_8_0
where ts=temp.timestamp-(temp.timestamp%3600)
and target=temp.target)';
FOR rec IN EXECUTE 'SELECT DISTINCT timestamp AS ts
FROM ' || temp_table_name ||
' WHERE class_id=8'
LOOP
EXECUTE 'update stat_300_8_0 as disk_table
set data[new_data.start_idx:new_data.end_idx] = array[data_0,data_1]
from (select timestamp-(timestamp%3600) as wide_row_ts,
(timestamp%3600)/300 * 2 + 1 as start_idx,
((timestamp%3600 / 300) + 1) * 2 as end_idx,
target, data_0, data_1
from ' || temp_table_name ||
' where class_id=8 and subclass_id=0
and timestamp=rec.ts) as new_data
where disk_table.ts=new_data.wide_row_ts
and disk_table.target=new_data.target';
END LOOP;
END;
However, when this function is executed I get an error saying
ERROR: missing FROM-clause entry for table "rec"
However, rec is declared in the first line of the above code. I am not able to figure what is wrong with my queries. Any help is appreciated.
Supplemental to Eelke's answer:
Assuming temp_table_name is an argument, you really, really want to run it through quote_ident() because otherwise someone could create a table with a name that could inject sql into your function.
Instead of the change suggested there, you are better off using EXECUTE...USING since that gives you parameterization regarding values (and hence protection against SQL injection). You would change rec.ts to $1 and then add to the end USING ts.rec (outside the quoted execute string). This gives you a parameterized statement inside your execute which is safer. However parameters cannot include table names, so it doesn't spare you from the first point above.
I am building a trigger function in plpgsql for my partitioned table and I've got all of my logic working, but am having trouble inserting the actual record into my table.
I have to reference my specific table by a variable reference, so that (as far as I understand) forces me to use an EXECUTE command, as so:
EXECUTE 'INSERT INTO ' || tablename || ' VALUES ' || NEW.*;
However, this does not handle unpacking the record stored in NEW in a way that Postgres' INSERT function can understand. It converts the record into a string while preserving all of the double quotes within. I.e. the above turns into the following upon execution:
INSERT INTO cfs_hgt_05152016_05202016
VALUES ("2016-05-16 00:00:00","2016-05-12 06:00:00",HGT,"1000 mb",9,-71,-38.5371)
The problem with this is Postgres thinks these values are now columns due to the double quotes.
COPY cfs_hgt_master, line 1: ""2016-05-16 00:00:00","2016-05-12 06:00:00","HGT","1000 mb",9,-71,-38.5371"
ERROR: column "2016-05-16 00:00:00" does not exist
I tried to remedy this by the following:
record_text := regexp_replace(NEW.*, '"', '\'', 'gi');
EXECUTE 'INSERT INTO ' || tablename || ' VALUES ' || record_text;
But escaping the single quote like that produces an error:
psql:cfs_hgt_trigger_function.sql:36: ERROR: unterminated quoted string at or near "' || record_text;
LINE 30: ... EXECUTE 'INSERT INTO ' || tablename || ' VALUES ' || recor...
^
Could someone help me figure out how to either properly escape that single quote, or suggest an alternative means of accomplishing my task?
Don't convert values to their text representation at all. Pass values with the USING clause of EXECUTE.
And escape table names properly. You can use format() for this:
EXECUTE format('INSERT INTO %I SELECT $1.*', tablename)
USING NEW;
Details:
INSERT with dynamic table name in trigger function
How to pass NEW.* to EXECUTE in trigger function
I am trying to test if pgrouting works fine or not. To do so I have created a table containing the following attributes.
Columns:
gid |
length |
the_geom |
source |
target
Now my problem is that when I try to execute the assign_vertex_id function it is giving me the following error;
PL/pgSQL function "assign_vertex_id" line 15 at EXECUTE statement
ERROR: query string argument of EXECUTE is null
CONTEXT: PL/pgSQL function "assign_vertex_id" line 32 at EXECUTE statement
********** Error **********
ERROR: query string argument of EXECUTE is null
SQL state: 22004
Context: PL/pgSQL function "assign_vertex_id" line 32 at EXECUTE statement
Any suggestions what does this mean?
assign_vertex_id() is defined as part of PGrouting in routing_topology.sql. (Running \df+ assign_vertex_id would also give you the current source.) Line 32's EXECUTE statement is:
EXECUTE 'update ' || quote_ident(geom_table) ||
' SET source = ' || source_id ||
', target = ' || target_id ||
' WHERE ' || quote_ident(gid_cname) || ' = ' || _r.id;
The error is that EXECUTE is being called with a NULL argument. How? Well, the SQL || operator means concatenate, and concatenating NULL to a string results in NULL:
=> select ('string' || null) is null;
?column?
----------
t
(1 row)
My guess is the gid column of the underlying table (_r.id here) contains NULLs, although I suppose it could be source/target_id too. Fix it, then add a constraint to prevent that going forward:
ALTER TABLE whatever ALTER COLUMN gid SET NOT NULL;
Are you using Postgis 2.0 and have a table with Multilinestrings?
The function ST_StartPoint() and ST_EndPoint() does not work on Multilinestrings anymore(http://postgis.refractions.net/docs/ST_StartPoint.html) in Postgis 2.0. So it will most likely fail there.
You need to convert your Multilinestrings to Linestrings. More info about that here: