diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
new file mode 100644
index aa19e10..3195655
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 2998,3011 ****
I treats the argument value as an SQL
identifier, double-quoting it if necessary.
! It is an error for the value to be null.
L quotes the argument value as an SQL literal.
A null value is displayed as the string NULL>, without
! quotes.
--- 2998,3012 ----
I treats the argument value as an SQL
identifier, double-quoting it if necessary.
! It is an error for the value to be null (equivalent to
! quote_ident>).
L quotes the argument value as an SQL literal.
A null value is displayed as the string NULL>, without
! quotes (equivalent to quote_nullable).
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
new file mode 100644
index 158d9d2..451cbb4
*** a/doc/src/sgml/plpgsql.sgml
--- b/doc/src/sgml/plpgsql.sgml
*************** EXECUTE 'SELECT count(*) FROM mytable WH
*** 1217,1227 ****
dynamically selected table, you could do this:
EXECUTE 'SELECT count(*) FROM '
! || tabname::regclass
|| ' WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;
Another restriction on parameter symbols is that they only work in
SELECT>, INSERT>, UPDATE>, and
DELETE> commands. In other statement
--- 1217,1234 ----
dynamically selected table, you could do this:
EXECUTE 'SELECT count(*) FROM '
! || quote_ident(tabname)
|| ' WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;
+ A cleaner approach is to use format()>'s %I>
+ specification for table or column names:
+
+ EXECUTE format('SELECT count(*) FROM %I WHERE inserted_by = $1 AND inserted <= $2', tabname)
+ INTO c
+ USING checked_user, checked_date;
+
Another restriction on parameter symbols is that they only work in
SELECT>, INSERT>, UPDATE>, and
DELETE> commands. In other statement
*************** EXECUTE 'SELECT count(*) FROM '
*** 1297,1307 ****
! Dynamic values that are to be inserted into the constructed
! query require careful handling since they might themselves contain
quote characters.
! An example (this assumes that you are using dollar quoting for the
! function as a whole, so the quote marks need not be doubled):
EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
--- 1304,1317 ----
! Dynamic values require careful handling since they might contain
quote characters.
! An example using format()> (this assumes that you are
! dollar quoting the function body so quote marks need not be doubled):
!
! EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname) USING newvalue, keyvalue;
!
! It is also possible to call the quoting functions directly:
EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
*************** EXECUTE 'UPDATE tbl SET '
*** 1393,1407 ****
EXECUTE format('UPDATE tbl SET %I = %L WHERE key = %L', colname, newvalue, keyvalue);
The format function can be used in conjunction with
the USING clause:
EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname)
USING newvalue, keyvalue;
! This form is more efficient, because the parameters
! newvalue and keyvalue are not
! converted to text.
--- 1403,1419 ----
EXECUTE format('UPDATE tbl SET %I = %L WHERE key = %L', colname, newvalue, keyvalue);
+ %I> is equivalent to quote_ident>, and
+ %L> is equivalent to quote_nullable.
The format function can be used in conjunction with
the USING clause:
EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname)
USING newvalue, keyvalue;
! This form is better because the variables are handled in their native
! data type format, rather than unconditionally converting them to
! text and quoting them via %L>. It is also more efficient.
*************** BEGIN
*** 2352,2361 ****
-- Now "mviews" has one record from cs_materialized_views
RAISE NOTICE 'Refreshing materialized view %s ...', quote_ident(mviews.mv_name);
! EXECUTE 'TRUNCATE TABLE ' || quote_ident(mviews.mv_name);
! EXECUTE 'INSERT INTO '
! || quote_ident(mviews.mv_name) || ' '
! || mviews.mv_query;
END LOOP;
RAISE NOTICE 'Done refreshing materialized views.';
--- 2364,2371 ----
-- Now "mviews" has one record from cs_materialized_views
RAISE NOTICE 'Refreshing materialized view %s ...', quote_ident(mviews.mv_name);
! EXECUTE format('TRUNCATE TABLE %I', mviews.mv_name);
! EXECUTE format('INSERT INTO %I %s', mviews.mv_name, mviews.mv_query);
END LOOP;
RAISE NOTICE 'Done refreshing materialized views.';
*************** OPEN unbound_cursorvar),
and it also means that variable substitution is not done on the
command string. As with EXECUTE, parameter values
! can be inserted into the dynamic command via USING>.
The SCROLL> and
NO SCROLL> options have the same meanings as for a bound
cursor.
--- 2978,2985 ----
from one run to the next (see ),
and it also means that variable substitution is not done on the
command string. As with EXECUTE, parameter values
! can be inserted into the dynamic command via
! format()> and USING>.
The SCROLL> and
NO SCROLL> options have the same meanings as for a bound
cursor.
*************** OPEN unbound_cursorvar
An example:
! OPEN curs1 FOR EXECUTE 'SELECT * FROM ' || quote_ident(tabname)
! || ' WHERE col1 = $1' USING keyvalue;
! In this example, the table name is inserted into the query textually,
! so use of quote_ident()> is recommended to guard against
! SQL injection. The comparison value for col1> is inserted
! via a USING> parameter, so it needs no quoting.
--- 2988,2999 ----
An example:
! OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING keyvalue;
! In this example, the table name is inserted into the query via
! format()>. The comparison value for col1>
! is inserted via a USING> parameter, so it needs
! no quoting.