Hi,

The other infrastructure patch that has been mark ready for commit then
commented further upon by Tom is $subject, even if the function provided
as been renamed to pg_execute_sql_file().

Please find attached the newer version that fixes Tom concerns, removing
the VARIADIC forms of the functions (those placeholders idea).

The git tree already contains a fixed extension code, but the next patch
for that one will have to wait some more (psql refactoring).

Regards,
-- 
Dimitri Fontaine
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support

*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 14449,14466 **** postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
        </row>
        <row>
         <entry>
!         <literal><function>pg_read_file(<parameter>filename</> <type>text</>, <parameter>offset</> <type>bigint</>, <parameter>length</> <type>bigint</>)</function></literal>
         </entry>
         <entry><type>text</type></entry>
         <entry>Return the contents of a text file</entry>
        </row>
        <row>
         <entry>
          <literal><function>pg_stat_file(<parameter>filename</> <type>text</>)</function></literal>
         </entry>
         <entry><type>record</type></entry>
         <entry>Return information about a file</entry>
        </row>
       </tbody>
      </tgroup>
     </table>
--- 14449,14488 ----
        </row>
        <row>
         <entry>
!         <literal><function>pg_read_file(<parameter>filename</> <type>text</>, <parameter>offset</> <type>bigint</> [, <parameter>length</> <type>bigint</>])</function></literal>
         </entry>
         <entry><type>text</type></entry>
         <entry>Return the contents of a text file</entry>
        </row>
        <row>
         <entry>
+         <literal><function>pg_read_binary_file(<parameter>filename</> <type>text</>, <parameter>offset</> <type>bigint</> [, <parameter>length</> <type>bigint</>])</function></literal>
+        </entry>
+        <entry><type>bytea</type></entry>
+        <entry>Return the contents of a file</entry>
+       </row>
+       <row>
+        <entry>
          <literal><function>pg_stat_file(<parameter>filename</> <type>text</>)</function></literal>
         </entry>
         <entry><type>record</type></entry>
         <entry>Return information about a file</entry>
        </row>
+       <row>
+        <entry>
+         <literal><function>pg_execute_sql_string(<parameter>sql</> <type>text</>) )</function></literal>
+        </entry>
+        <entry><type>void</type></entry>
+        <entry>Execute the given string as <acronym>SQL</> commands.</entry>
+       </row>
+       <row>
+        <entry>
+         <literal><function>pg_execute_sql_file(<parameter>filename</> <type>text</> [, <parameter>encoding</parameter> <type>name</type>]) )</function></literal>
+        </entry>
+        <entry><type>void</type></entry>
+        <entry>Execute contents of the given file as <acronym>SQL</> commands,
+        expected in either database encoding or given encoding.</entry>
+       </row>
       </tbody>
      </tgroup>
     </table>
***************
*** 14482,14487 **** postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
--- 14504,14533 ----
      at the given <parameter>offset</>, returning at most <parameter>length</>
      bytes (less if the end of file is reached first).  If <parameter>offset</>
      is negative, it is relative to the end of the file.
+     When the parameter <parameter>length</> is omitted,
+     <function>pg_read_file</> reads until the end of the file.
+     The part of a file must be a valid text in the server encoding.
+    </para>
+ 
+    <indexterm>
+     <primary>pg_read_binary_file</primary>
+    </indexterm>
+    <para>
+     <function>pg_read_binary_file</> returns part of a file as like as
+     <function>pg_read_file</>, but the result is a bytea value.
+ <programlisting>
+ SELECT convert_from(pg_read_binary_file('postgresql.conf', -69), 'utf8');
+                                  convert_from                                  
+ -------------------------------------------------------------------------------
+  #custom_variable_classes = ''           # list of custom variable class names+
+  
+ (1 row)
+ </programlisting>
+    </para>
+    <para>
+     When the parameter <parameter>length</> is
+     omited, <function>pg_read_binary_file</> reads until the end of the
+     file.
     </para>
  
     <indexterm>
***************
*** 14499,14504 **** SELECT (pg_stat_file('filename')).modification;
--- 14545,14582 ----
  </programlisting>
     </para>
  
+    <indexterm>
+     <primary>pg_execute_sql_string</primary>
+    </indexterm>
+    <para>
+     <function>pg_execute_sql_string</> makes the server execute the given string
+     as <acronym>SQL</> commands.
+     The script may contain placeholders that will be replaced by the optional
+     parameters, that are pairs of variable names and values. Here's an example:
+ <programlisting>
+ SELECT pg_execute_sql_string('CREATE SCHEMA utils');
+  pg_execute_sql_string 
+ -----------------------
+  
+ (1 row)
+ 
+ SELECT oid, * from pg_namespace where nspname = 'utils';
+   oid  | nspname | nspowner | nspacl 
+ -------+---------+----------+--------
+  16387 | utils   |       10 | 
+ (2 rows)
+ </programlisting>
+    </para>
+ 
+    <indexterm>
+     <primary>pg_execute_sql_file</primary>
+    </indexterm>
+    <para>
+     <function>pg_execute_sql_file</> makes the server execute contents in a file
+     as <acronym>SQL</> commands. You can give an encoding name of the file to the
+     function. If omitted, the server encoding is used.
+    </para>
+ 
     <para>
      The functions shown in <xref linkend="functions-advisory-locks"> manage
      advisory locks.  For details about proper use of these functions, see
*** a/src/backend/utils/adt/genfile.c
--- b/src/backend/utils/adt/genfile.c
***************
*** 21,31 ****
--- 21,33 ----
  #include <dirent.h>
  
  #include "catalog/pg_type.h"
+ #include "executor/spi.h"
  #include "funcapi.h"
  #include "mb/pg_wchar.h"
  #include "miscadmin.h"
  #include "postmaster/syslogger.h"
  #include "storage/fd.h"
+ #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/memutils.h"
  #include "utils/timestamp.h"
***************
*** 80,104 **** convert_and_check_filename(text *arg)
  
  
  /*
!  * Read a section of a file, returning it as text
   */
! Datum
! pg_read_file(PG_FUNCTION_ARGS)
  {
! 	text	   *filename_t = PG_GETARG_TEXT_P(0);
! 	int64		seek_offset = PG_GETARG_INT64(1);
! 	int64		bytes_to_read = PG_GETARG_INT64(2);
! 	char	   *buf;
! 	size_t		nbytes;
! 	FILE	   *file;
! 	char	   *filename;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to read files"))));
  
! 	filename = convert_and_check_filename(filename_t);
  
  	if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
  		ereport(ERROR,
--- 82,126 ----
  
  
  /*
!  * Read a section of a file, returning it as bytea
!  *
!  * Will read all the file if given a nagative bytes_to_read, and a negative
!  * offset is applied from the end of the file (SEEK_END)
   */
! static bytea *
! read_binary_file(const char *filename, int64 offset, int64 bytes_to_read)
  {
! 	FILE       *file;
! 	bytea      *buf;
! 	int64       nbytes;
  
+ 	/* Only superuser can read files. */
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to read files"))));
  
! 	if (bytes_to_read >= 0)
! 		nbytes = bytes_to_read;
! 	else if (offset < 0)
! 		nbytes = -offset;
! 	else
! 	{
! 		struct stat fst;
! 
! 		if (stat(filename, &fst) < 0)
! 			ereport(ERROR,
! 					(errcode_for_file_access(),
! 					 errmsg("could not stat file \"%s\": %m", filename)));
! 
! 		nbytes = fst.st_size;
! 	}
! 
! 	/* not sure why anyone thought that int64 length was a good idea */
! 	if (nbytes > (MaxAllocSize - VARHDRSZ))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("requested length too large")));
  
  	if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
  		ereport(ERROR,
***************
*** 106,146 **** pg_read_file(PG_FUNCTION_ARGS)
  				 errmsg("could not open file \"%s\" for reading: %m",
  						filename)));
  
! 	if (fseeko(file, (off_t) seek_offset,
! 			   (seek_offset >= 0) ? SEEK_SET : SEEK_END) != 0)
  		ereport(ERROR,
  				(errcode_for_file_access(),
  				 errmsg("could not seek in file \"%s\": %m", filename)));
  
! 	if (bytes_to_read < 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("requested length cannot be negative")));
  
! 	/* not sure why anyone thought that int64 length was a good idea */
! 	if (bytes_to_read > (MaxAllocSize - VARHDRSZ))
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("requested length too large")));
  
! 	buf = palloc((Size) bytes_to_read + VARHDRSZ);
  
! 	nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
  
! 	if (ferror(file))
  		ereport(ERROR,
! 				(errcode_for_file_access(),
! 				 errmsg("could not read file \"%s\": %m", filename)));
! 
! 	/* Make sure the input is valid */
! 	pg_verifymbstr(VARDATA(buf), nbytes, false);
  
! 	SET_VARSIZE(buf, nbytes + VARHDRSZ);
  
! 	FreeFile(file);
! 	pfree(filename);
  
! 	PG_RETURN_TEXT_P(buf);
  }
  
  /*
--- 128,270 ----
  				 errmsg("could not open file \"%s\" for reading: %m",
  						filename)));
  
! 	if (fseeko(file, (off_t) offset,
! 			   (offset >= 0) ? SEEK_SET : SEEK_END) != 0)
  		ereport(ERROR,
  				(errcode_for_file_access(),
  				 errmsg("could not seek in file \"%s\": %m", filename)));
  
! 	buf = (bytea *) palloc((Size) nbytes + VARHDRSZ);
! 	nbytes = fread(VARDATA(buf), 1, (size_t) nbytes, file);
! 
! 	if (ferror(file))
! 		ereport(ERROR,
! 				(errcode_for_file_access(),
! 				 errmsg("could not read file \"%s\": %m", filename)));
! 
! 	FreeFile(file);
! 
! 	SET_VARSIZE(buf, nbytes + VARHDRSZ);
! 
! 	return buf;
! }
! 
! /*
!  * In addition to read_binary_file, verify the contents are encoded in the
!  * database encoding.
!  */
! static text *
! read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read)
! {
! 	bytea *content = read_binary_file(filename, seek_offset, bytes_to_read);
! 
! 	/* Make sure the input is valid */
! 	pg_verifymbstr(VARDATA(content), VARSIZE(content) - VARHDRSZ, false);
! 
! 	/* Abuse knowledge that we're bytea and text are both varlena */
! 	return (text *) content;
! }
! 
! /*
!  * read given file and return the content converted to given encoding
!  */
! char *
! read_text_file_with_endoding(const char *filename, const char *encoding_name)
! {
! 	int			src_encoding;
! 	int			dest_encoding = GetDatabaseEncoding();
! 	bytea      *content;
! 	const char *src_str;
! 	char	   *dest_str;
! 	int			len;
! 
! 	/* use database encoding if not given */
! 	if (encoding_name == NULL)
! 		src_encoding = dest_encoding;
! 	else
! 		src_encoding = pg_char_to_encoding(encoding_name);
! 
! 	if (src_encoding < 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("invalid source encoding name \"%s\"",
! 						encoding_name)));
! 
! 	/* superuser checks will be done in reading files */
! 	content = read_binary_file(filename, 0, -1);
! 
! 	/* make sure that source string is valid */
! 	len = VARSIZE_ANY_EXHDR(content);
! 	src_str = VARDATA_ANY(content);
! 	pg_verify_mbstr_len(src_encoding, src_str, len, false);
! 
! 	/* convert the encoding to the database encoding */
! 	dest_str = (char *) pg_do_encoding_conversion(
! 				(unsigned char *) src_str, len, src_encoding, dest_encoding);
! 	if (dest_str != src_str)
! 		return dest_str;
! 	else
! 		return text_to_cstring((text *)content);
! }
  
! /*
!  * Read a section of a file, returning its content as text
!  */
! Datum
! pg_read_file(PG_FUNCTION_ARGS)
! {
! 	char       *filename = text_to_cstring(PG_GETARG_TEXT_PP(0));
! 	int64		seek_offset = PG_GETARG_INT64(1);
! 	int64		bytes_to_read = PG_GETARG_INT64(2);
! 
! 	if (bytes_to_read < 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("requested length cannot be negative")));
! 
! 	PG_RETURN_TEXT_P(read_text_file(filename, seek_offset, bytes_to_read));
! }
! 
! /*
!  * Read till the end of a file, returning its content as text
!  */
! Datum
! pg_read_whole_file(PG_FUNCTION_ARGS)
! {
! 	char       *filename = text_to_cstring(PG_GETARG_TEXT_PP(0));
! 	int64		seek_offset = PG_GETARG_INT64(1);
  
! 	PG_RETURN_TEXT_P(read_text_file(filename, seek_offset, -1));
! }
  
! /*
!  * Read a section of a file, returning its content as bytea
!  */
! Datum
! pg_read_binary_file(PG_FUNCTION_ARGS)
! {
! 	char       *filename = text_to_cstring(PG_GETARG_TEXT_PP(0));
! 	int64		seek_offset = PG_GETARG_INT64(1);
! 	int64		bytes_to_read = PG_GETARG_INT64(2);
  
! 	if (bytes_to_read < 0)
  		ereport(ERROR,
! 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("requested length cannot be negative")));
  
! 	PG_RETURN_BYTEA_P(read_binary_file(filename, seek_offset, bytes_to_read));
! }
  
! /*
!  * Read till the end of a file, returning its content as bytea
!  */
! Datum
! pg_read_whole_binary_file(PG_FUNCTION_ARGS)
! {
! 	char       *filename = text_to_cstring(PG_GETARG_TEXT_PP(0));
! 	int64		seek_offset = PG_GETARG_INT64(1);
  
! 	PG_RETURN_BYTEA_P(read_binary_file(filename, seek_offset, -1));
  }
  
  /*
***************
*** 149,155 **** pg_read_file(PG_FUNCTION_ARGS)
  Datum
  pg_stat_file(PG_FUNCTION_ARGS)
  {
! 	text	   *filename_t = PG_GETARG_TEXT_P(0);
  	char	   *filename;
  	struct stat fst;
  	Datum		values[6];
--- 273,279 ----
  Datum
  pg_stat_file(PG_FUNCTION_ARGS)
  {
! 	text	   *filename_t = PG_GETARG_TEXT_PP(0);
  	char	   *filename;
  	struct stat fst;
  	Datum		values[6];
***************
*** 234,240 **** pg_ls_dir(PG_FUNCTION_ARGS)
  		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
  
  		fctx = palloc(sizeof(directory_fctx));
! 		fctx->location = convert_and_check_filename(PG_GETARG_TEXT_P(0));
  
  		fctx->dirdesc = AllocateDir(fctx->location);
  
--- 358,364 ----
  		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
  
  		fctx = palloc(sizeof(directory_fctx));
! 		fctx->location = convert_and_check_filename(PG_GETARG_TEXT_PP(0));
  
  		fctx->dirdesc = AllocateDir(fctx->location);
  
***************
*** 264,266 **** pg_ls_dir(PG_FUNCTION_ARGS)
--- 388,466 ----
  
  	SRF_RETURN_DONE(funcctx);
  }
+ 
+ /*
+  * Execute given SQL string.
+  */
+ void
+ execute_sql_string(const char *filename, const char *sql)
+ {
+ 	/*
+ 	 * We abuse some internal knowledge from spi.h here. As we don't know
+ 	 * which queries are going to get executed, we don't know what to expect
+ 	 * as an OK return code from SPI_execute().  We assume that
+ 	 * SPI_OK_CONNECT, SPI_OK_FINISH and SPI_OK_FETCH are quite improbable,
+ 	 * though, and the errors are negatives.  So a valid return code is
+ 	 * considered to be SPI_OK_UTILITY or anything from there.
+ 	 */
+ 	if (SPI_connect() != SPI_OK_CONNECT)
+ 		elog(ERROR, "SPI_connect failed");
+ 
+ 	if (SPI_execute(sql, false, 0) < SPI_OK_UTILITY)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_DATA_EXCEPTION),
+ 				 (filename != NULL
+ 				  ? errmsg("could not execute sql file: '%s'", filename)
+ 				  : errmsg("could not execute sql string"))));
+ 
+ 	if (SPI_finish() != SPI_OK_FINISH)
+ 		elog(ERROR, "SPI_finish failed");
+ }
+ 
+ /*
+  * Execute given SQL file's content in given encoding
+  */
+ void
+ execute_sql_file(const char *filename, const char *encoding_name)
+ {
+ 	execute_sql_string(filename,
+ 					   read_text_file_with_endoding(filename, encoding_name));
+ }
+ 
+ /*
+  * Execute SQL string.
+  */
+ Datum
+ pg_execute_sql_string(PG_FUNCTION_ARGS)
+ {
+ 	text	   *sql = PG_GETARG_TEXT_PP(0);
+ 
+ 	execute_sql_string(NULL, text_to_cstring(sql));
+ 	PG_RETURN_VOID();
+ }
+ 
+ /*
+  * Read a file, and execute the contents as SQL commands.
+  */
+ Datum
+ pg_execute_sql_file(PG_FUNCTION_ARGS)
+ {
+ 	char       *filename = text_to_cstring(PG_GETARG_TEXT_PP(0));
+ 
+ 	execute_sql_file(filename, NULL);
+ 	PG_RETURN_VOID();
+ }
+ 
+ /*
+  * In addition to pg_execute_sql_file, convert the encoding of the contents
+  * to the database encoding.
+  */
+ Datum
+ pg_convert_and_execute_sql_file(PG_FUNCTION_ARGS)
+ {
+ 	char       *filename = text_to_cstring(PG_GETARG_TEXT_PP(0));
+ 	char	   *encoding_name = NameStr(*PG_GETARG_NAME(1));
+ 
+ 	execute_sql_file(filename, encoding_name);
+ 	PG_RETURN_VOID();
+ }
*** a/src/backend/utils/adt/varlena.c
--- b/src/backend/utils/adt/varlena.c
***************
*** 24,29 ****
--- 24,30 ----
  #include "miscadmin.h"
  #include "parser/scansup.h"
  #include "regex/regex.h"
+ #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/bytea.h"
  #include "utils/lsyscache.h"
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 3399,3412 **** DESCR("reload configuration files");
  DATA(insert OID = 2622 ( pg_rotate_logfile		PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ ));
  DESCR("rotate log file");
  
! DATA(insert OID = 2623 ( pg_stat_file		PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" _null_ pg_stat_file _null_ _null_ _null_ ));
  DESCR("return file information");
! DATA(insert OID = 2624 ( pg_read_file		PGNSP PGUID 12 1 0 0 f f f t f v 3 0 25 "25 20 20" _null_ _null_ _null_ _null_ pg_read_file _null_ _null_ _null_ ));
  DESCR("read text from a file");
! DATA(insert OID = 2625 ( pg_ls_dir			PGNSP PGUID 12 1 1000 0 f f f t t v 1 0 25 "25" _null_ _null_ _null_ _null_ pg_ls_dir _null_ _null_ _null_ ));
  DESCR("list all files in a directory");
! DATA(insert OID = 2626 ( pg_sleep			PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "701" _null_ _null_ _null_ _null_ pg_sleep _null_ _null_ _null_ ));
  DESCR("sleep for the specified time in seconds");
  
  DATA(insert OID = 2971 (  text				PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "16" _null_ _null_ _null_ _null_ booltext _null_ _null_ _null_ ));
  DESCR("convert boolean to text");
--- 3399,3424 ----
  DATA(insert OID = 2622 ( pg_rotate_logfile		PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ ));
  DESCR("rotate log file");
  
! DATA(insert OID = 2623 ( pg_stat_file			PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" _null_ pg_stat_file _null_ _null_ _null_ ));
  DESCR("return file information");
! DATA(insert OID = 2624 ( pg_read_file			PGNSP PGUID 12 1 0 0 f f f t f v 3 0 25 "25 20 20" _null_ _null_ _null_ _null_ pg_read_file _null_ _null_ _null_ ));
  DESCR("read text from a file");
! DATA(insert OID = 3935 ( pg_read_file			PGNSP PGUID 12 1 0 0 f f f t f v 2 0 25 "25 20" _null_ _null_ _null_ _null_ pg_read_whole_file _null_ _null_ _null_ ));
! DESCR("read text from a file");
! DATA(insert OID = 2625 ( pg_ls_dir				PGNSP PGUID 12 1 1000 0 f f f t t v 1 0 25 "25" _null_ _null_ _null_ _null_ pg_ls_dir _null_ _null_ _null_ ));
  DESCR("list all files in a directory");
! DATA(insert OID = 2626 ( pg_sleep				PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "701" _null_ _null_ _null_ _null_ pg_sleep _null_ _null_ _null_ ));
  DESCR("sleep for the specified time in seconds");
+ DATA(insert OID = 3930 ( pg_read_binary_file	PGNSP PGUID 12 1 0 0 f f f t f v 3 0 17 "25 20 20" _null_ _null_ _null_ _null_ pg_read_binary_file _null_ _null_ _null_ ));
+ DESCR("read bytea from a file");
+ DATA(insert OID = 3936 ( pg_read_binary_file	PGNSP PGUID 12 1 0 0 f f f t f v 2 0 17 "25 20" _null_ _null_ _null_ _null_ pg_read_whole_binary_file _null_ _null_ _null_ ));
+ DESCR("read bytea from a file");
+ DATA(insert OID = 3932 ( pg_execute_sql_string	PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "25" _null_ _null_ _null_ _null_ pg_execute_sql_string _null_ _null_ _null_ ));
+ DESCR("execute queries read from a string");
+ DATA(insert OID = 3927 ( pg_execute_sql_file	PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2278 "25" _null_ _null_ _null_ _null_ pg_execute_sql_file _null_ _null_ _null_ ));
+ DESCR("execute queries read from a file");
+ DATA(insert OID = 3934 ( pg_execute_sql_file	PGNSP PGUID 12 1 0 0 f f f t f v 2 0 2278 "25 19" _null_ _null_ _null_ _null_ pg_convert_and_execute_sql_file _null_ _null_ _null_ ));
+ DESCR("execute queries read from a file");
  
  DATA(insert OID = 2971 (  text				PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "16" _null_ _null_ _null_ _null_ booltext _null_ _null_ _null_ ));
  DESCR("convert boolean to text");
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 442,448 **** extern Datum pg_relation_filepath(PG_FUNCTION_ARGS);
--- 442,455 ----
  /* genfile.c */
  extern Datum pg_stat_file(PG_FUNCTION_ARGS);
  extern Datum pg_read_file(PG_FUNCTION_ARGS);
+ extern Datum pg_read_whole_file(PG_FUNCTION_ARGS);
+ extern Datum pg_read_binary_file(PG_FUNCTION_ARGS);
+ extern Datum pg_read_whole_binary_file(PG_FUNCTION_ARGS);
  extern Datum pg_ls_dir(PG_FUNCTION_ARGS);
+ extern Datum replace_placeholders(PG_FUNCTION_ARGS);
+ extern Datum pg_execute_sql_string(PG_FUNCTION_ARGS);
+ extern Datum pg_execute_sql_file(PG_FUNCTION_ARGS);
+ extern Datum pg_convert_and_execute_sql_file(PG_FUNCTION_ARGS);
  
  /* misc.c */
  extern Datum current_database(PG_FUNCTION_ARGS);
*** /dev/null
--- b/src/include/utils/genfile.h
***************
*** 0 ****
--- 1,28 ----
+ /*--------------------------------------------------------------------
+  * genfile.h
+  *
+  * External declarations pertaining to backend/utils/misc/genfile.c
+  *
+  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
+  *
+  * src/include/utils/genfile.h
+  *--------------------------------------------------------------------
+  */
+ #ifndef GENFILE_H
+ #define GENFILE_H
+ 
+ #include <dirent.h>
+ #include "utils/array.h"
+ 
+ typedef struct
+ {
+ 	char	   *location;
+ 	DIR		   *dirdesc;
+ } directory_fctx;
+ 
+ char *read_text_file_with_endoding(const char *filename,
+ 										const char *encoding_name);
+ void execute_sql_string(const char *filename, const char *sql);
+ void execute_sql_file(const char *filename, const char *encoding_name);
+ 
+ #endif   /* GENFILE_H */
*** a/src/test/regress/expected/strings.out
--- b/src/test/regress/expected/strings.out
***************
*** 1603,1605 **** SELECT encode(overlay(E'Th\\000omas'::bytea placing E'\\002\\003'::bytea from 5
--- 1603,1616 ----
   Th\000o\x02\x03
  (1 row)
  
+ --
+ -- test execute
+ --
+ SELECT pg_execute_sql_string($do$ DO $$BEGIN RAISE INFO 'foo'; END;$$ $do$);
+ INFO:  foo
+ CONTEXT:  SQL statement " DO $$BEGIN RAISE INFO 'foo'; END;$$ "
+  pg_execute_sql_string 
+ -----------------------
+  
+ (1 row)
+ 
*** a/src/test/regress/sql/strings.sql
--- b/src/test/regress/sql/strings.sql
***************
*** 552,554 **** SELECT btrim(E'\\000trim\\000'::bytea, ''::bytea);
--- 552,559 ----
  SELECT encode(overlay(E'Th\\000omas'::bytea placing E'Th\\001omas'::bytea from 2),'escape');
  SELECT encode(overlay(E'Th\\000omas'::bytea placing E'\\002\\003'::bytea from 8),'escape');
  SELECT encode(overlay(E'Th\\000omas'::bytea placing E'\\002\\003'::bytea from 5 for 3),'escape');
+ 
+ --
+ -- test execute
+ --
+ SELECT pg_execute_sql_string($do$ DO $$BEGIN RAISE INFO 'foo'; END;$$ $do$);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to