1996-07-09 06:22:35 +00:00
/*-------------------------------------------------------------------------
*
1999-02-13 23:22:53 +00:00
* pg_dump . c
1997-09-07 05:04:48 +00:00
* pg_dump is an utility for dumping out a postgres database
1996-07-09 06:22:35 +00:00
* into a script file .
*
1997-09-07 05:04:48 +00:00
* pg_dump will read the system catalogs in a database and
* dump out a script that reproduces
* the schema of the database in terms of
* user - defined types
* user - defined functions
* tables
* indices
* aggregates
* operators
* ACL - grant / revoke
1996-07-09 06:22:35 +00:00
*
1997-04-12 09:24:23 +00:00
* the output script is SQL that is understood by PostgreSQL
1996-07-09 06:22:35 +00:00
*
2000-01-26 05:58:53 +00:00
* Portions Copyright ( c ) 1996 - 2000 , PostgreSQL , Inc
* Portions Copyright ( c ) 1994 , Regents of the University of California
1996-07-09 06:22:35 +00:00
*
*
* IDENTIFICATION
2000-02-07 16:30:58 +00:00
* $ Header : / cvsroot / pgsql / src / bin / pg_dump / pg_dump . c , v 1.144 2000 / 02 / 07 16 : 30 : 58 wieck Exp $
1996-07-12 05:39:39 +00:00
*
1996-07-22 08:37:00 +00:00
* Modifications - 6 / 10 / 96 - dave @ bensoft . com - version 1.13 . dhb
1996-07-12 05:39:39 +00:00
*
1997-09-07 05:04:48 +00:00
* Applied ' insert string ' patch from " Marc G. Fournier " < scrappy @ ki . net >
* Added ' - t table ' option
* Added ' - a ' option
* Added ' - da ' option
1996-07-09 06:22:35 +00:00
*
1996-07-22 08:37:00 +00:00
* Modifications - 6 / 12 / 96 - dave @ bensoft . com - version 1.13 . dhb .2
*
1997-09-07 05:04:48 +00:00
* - Fixed dumpTable output to output lengths for char and varchar types !
* - Added single . quote to twin single quote expansion for ' insert ' string
* mode .
1996-07-22 08:37:00 +00:00
*
1996-07-27 02:29:51 +00:00
* Modifications - 7 / 26 / 96 - asussman @ vidya . com
*
1997-09-07 05:04:48 +00:00
* - Fixed ouput lengths for char and varchar type where the length is variable ( - 1 )
1996-07-27 02:29:51 +00:00
*
1997-06-02 02:52:06 +00:00
* Modifications - 6 / 1 / 97 - igor @ sba . miami . edu
* - Added functions to free allocated memory used for retrieving
1997-09-07 05:04:48 +00:00
* indices , tables , inheritance , types , functions and aggregates .
* No more leaks reported by Purify .
1998-01-29 02:26:47 +00:00
*
*
* Modifications - 1 / 26 / 98 - pjlobo @ euitt . upm . es
1998-02-26 04:46:47 +00:00
* - Added support for password authentication
1996-07-09 06:22:35 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
1997-09-07 05:04:48 +00:00
# include <unistd.h> /* for getopt() */
1998-02-18 15:33:37 +00:00
# include <ctype.h>
1996-07-09 06:22:35 +00:00
# include "postgres.h"
1999-10-23 03:13:33 +00:00
# ifdef HAVE_GETOPT_H
# include <getopt.h>
# endif
# ifdef HAVE_TERMIOS_H
# include <termios.h>
# endif
# include "access/attnum.h"
1996-07-31 06:09:46 +00:00
# include "access/htup.h"
1997-05-06 05:20:21 +00:00
# include "catalog/pg_index.h"
1999-10-23 03:13:33 +00:00
# include "catalog/pg_language.h"
1997-10-02 13:57:07 +00:00
# include "catalog/pg_trigger.h"
1999-10-23 03:13:33 +00:00
# include "catalog/pg_type.h"
2000-01-18 00:03:37 +00:00
# include "version.h"
1999-07-15 15:21:54 +00:00
1996-07-09 06:22:35 +00:00
# include "libpq-fe.h"
1997-02-13 08:32:20 +00:00
# ifndef HAVE_STRDUP
1996-11-26 07:39:11 +00:00
# include "strdup.h"
# endif
1996-07-09 06:22:35 +00:00
# include "pg_dump.h"
2000-01-18 18:09:02 +00:00
static void dumpComment ( FILE * outfile , const char * target , const char * oid ) ;
1997-09-08 21:56:23 +00:00
static void dumpSequence ( FILE * fout , TableInfo tbinfo ) ;
1998-04-07 22:36:38 +00:00
static void dumpACL ( FILE * fout , TableInfo tbinfo ) ;
1998-09-01 04:40:42 +00:00
static void dumpTriggers ( FILE * fout , const char * tablename ,
1998-02-26 04:46:47 +00:00
TableInfo * tblinfo , int numTables ) ;
1998-10-06 22:14:21 +00:00
static void dumpRules ( FILE * fout , const char * tablename ,
1999-05-25 16:15:34 +00:00
TableInfo * tblinfo , int numTables ) ;
1997-09-08 02:41:22 +00:00
static char * checkForQuote ( const char * s ) ;
static void clearTableInfo ( TableInfo * , int ) ;
1998-09-01 04:40:42 +00:00
static void dumpOneFunc ( FILE * fout , FuncInfo * finfo , int i ,
1997-09-08 21:56:23 +00:00
TypeInfo * tinfo , int numTypes ) ;
1997-09-08 02:41:22 +00:00
static int findLastBuiltinOid ( void ) ;
static bool isViewRule ( char * relname ) ;
1997-09-08 21:56:23 +00:00
static void setMaxOid ( FILE * fout ) ;
1997-04-02 04:17:27 +00:00
1998-12-05 22:09:57 +00:00
static void AddAcl ( char * aclbuf , const char * keyword ) ;
static char * GetPrivileges ( const char * s ) ;
1998-07-19 05:24:51 +00:00
static void becomeUser ( FILE * fout , const char * username ) ;
1997-12-26 08:45:27 +00:00
1999-05-25 16:15:34 +00:00
extern char * optarg ;
1997-09-08 02:41:22 +00:00
extern int optind ,
1999-05-25 16:15:34 +00:00
opterr ;
1996-07-09 06:22:35 +00:00
/* global decls */
1997-09-08 02:41:22 +00:00
bool g_verbose ; /* User wants verbose narration of our
1999-05-25 16:15:34 +00:00
* activities . */
int g_last_builtin_oid ; /* value of the last builtin oid */
FILE * g_fout ; /* the script file */
PGconn * g_conn ; /* the database connection */
bool force_quotes ; /* User wants to suppress double-quotes */
1999-05-26 16:06:45 +00:00
bool dumpData ; /* dump data using proper insert strings */
bool attrNames ; /* put attr names into insert strings */
bool schemaOnly ;
bool dataOnly ;
1999-05-27 16:29:05 +00:00
bool aclsSkip ;
1999-05-26 16:06:45 +00:00
bool dropSchema ;
1997-09-07 05:04:48 +00:00
1999-05-25 16:15:34 +00:00
char g_opaque_type [ 10 ] ; /* name for the opaque type */
1996-07-09 06:22:35 +00:00
/* placeholders for the delimiters for comments */
1997-09-08 02:41:22 +00:00
char g_comment_start [ 10 ] ;
char g_comment_end [ 10 ] ;
1996-07-09 06:22:35 +00:00
static void
2000-01-18 00:03:37 +00:00
help ( const char * progname )
1996-07-09 06:22:35 +00:00
{
2000-02-02 13:20:15 +00:00
printf ( " %s dumps a database as a text file. \n \n " , progname ) ;
2000-01-18 00:03:37 +00:00
puts ( " Usage: " ) ;
printf ( " %s [options] dbname \n \n " , progname ) ;
puts ( " Options: " ) ;
1999-12-16 20:10:02 +00:00
# ifdef HAVE_GETOPT_LONG
2000-01-18 00:03:37 +00:00
puts (
" -a, --data-only dump out only the data, not the schema \n "
" -c, --clean clean (drop) schema prior to create \n "
" -d, --inserts dump data as INSERT, rather than COPY, commands \n "
" -D, --attribute-inserts dump data as INSERT commands with attribute names \n "
" -h, --host <hostname> server host name \n "
" -n, --no-quotes suppress most quotes around identifiers \n "
" -N, --quotes enable most quotes around identifiers \n "
2000-01-24 19:34:19 +00:00
" -o, --oids dump object ids (oids) \n "
2000-01-18 00:03:37 +00:00
" -p, --port <port> server port number \n "
" -s, --schema-only dump out only the schema, no data \n "
" -t, --table <table> dump for this table only \n "
" -u, --password use password authentication \n "
" -v, --verbose verbose \n "
" -x, --no-acl do not dump ACL's (grant/revoke) \n "
) ;
1999-12-16 20:10:02 +00:00
# else
2000-01-18 00:03:37 +00:00
puts (
" -a dump out only the data, no schema \n "
" -c clean (drop) schema prior to create \n "
" -d dump data as INSERT, rather than COPY, commands \n "
" -D dump data as INSERT commands with attribute names \n "
" -h <hostname> server host name \n "
" -n suppress most quotes around identifiers \n "
" -N enable most quotes around identifiers \n "
2000-01-24 19:34:19 +00:00
" -o dump object ids (oids) \n "
2000-01-18 00:03:37 +00:00
" -p <port> server port number \n "
" -s dump out only the schema, no data \n "
" -t <table> dump for this table only \n "
" -u use password authentication \n "
" -v verbose \n "
" -x do not dump ACL's (grant/revoke) \n "
) ;
1999-12-16 20:10:02 +00:00
# endif
2000-01-18 00:03:37 +00:00
puts ( " If no database name is not supplied, then the PGDATABASE environment \n variable value is used. \n " ) ;
2000-01-19 20:08:36 +00:00
puts ( " Report bugs to <pgsql-bugs@postgresql.org>. " ) ;
2000-01-18 00:03:37 +00:00
}
2000-01-10 17:14:46 +00:00
1997-09-07 05:04:48 +00:00
2000-01-18 00:03:37 +00:00
static void
version ( void )
{
puts ( " pg_dump (PostgreSQL) " PG_RELEASE " . " PG_VERSION " . " PG_SUBVERSION ) ;
2000-01-27 05:33:51 +00:00
puts ( " Portions Copyright (c) 1996-2000, PostgreSQL, Inc " ) ;
2000-01-26 05:58:53 +00:00
puts ( " Portions Copyright (C) 1996 Regents of the University of California " ) ;
2000-01-29 16:58:54 +00:00
puts ( " Read the file COPYRIGHT to see the usage and distribution terms. " ) ;
1996-07-09 06:22:35 +00:00
}
2000-01-18 00:03:37 +00:00
1997-09-07 05:04:48 +00:00
static void
1997-09-08 21:56:23 +00:00
exit_nicely ( PGconn * conn )
1996-07-09 06:22:35 +00:00
{
1997-09-07 05:04:48 +00:00
PQfinish ( conn ) ;
exit ( 1 ) ;
1996-07-09 06:22:35 +00:00
}
1997-01-07 00:04:19 +00:00
/*
* isViewRule
1997-09-07 05:04:48 +00:00
* Determine if the relation is a VIEW
1997-01-07 00:04:19 +00:00
*
*/
1997-09-08 02:41:22 +00:00
static bool
1997-01-07 00:04:19 +00:00
isViewRule ( char * relname )
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
int ntups ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " select relname from pg_class, pg_rewrite " ) ;
appendPQExpBuffer ( query , " where pg_class.oid = ev_class " ) ;
appendPQExpBuffer ( query , " and pg_rewrite.ev_type = '1' " ) ;
appendPQExpBuffer ( query , " and rulename = '_RET%s' " , relname ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " isViewRule(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
PQclear ( res ) ;
return ntups > 0 ? TRUE : FALSE ;
1997-01-07 00:04:19 +00:00
}
1996-12-27 23:12:57 +00:00
1997-09-07 05:04:48 +00:00
# define COPYBUFSIZ 8192
static void
1997-09-08 21:56:23 +00:00
dumpClasses_nodumpData ( FILE * fout , const char * classname , const bool oids )
1997-09-07 05:04:48 +00:00
{
1997-09-08 02:41:22 +00:00
PGresult * res ;
char query [ 255 ] ;
int ret ;
bool copydone ;
char copybuf [ COPYBUFSIZ ] ;
1997-09-07 05:04:48 +00:00
1999-05-26 16:06:45 +00:00
if ( oids = = true )
1997-09-07 05:04:48 +00:00
{
1998-08-25 15:02:04 +00:00
fprintf ( fout , " COPY %s WITH OIDS FROM stdin; \n " ,
1998-12-13 23:41:32 +00:00
fmtId ( classname , force_quotes ) ) ;
1998-08-25 15:02:04 +00:00
sprintf ( query , " COPY %s WITH OIDS TO stdout; \n " ,
1998-12-13 23:41:32 +00:00
fmtId ( classname , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
}
else
{
1998-12-13 23:41:32 +00:00
fprintf ( fout , " COPY %s FROM stdin; \n " , fmtId ( classname , force_quotes ) ) ;
sprintf ( query , " COPY %s TO stdout; \n " , fmtId ( classname , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
}
res = PQexec ( g_conn , query ) ;
1998-05-06 23:53:48 +00:00
if ( ! res | |
PQresultStatus ( res ) = = PGRES_FATAL_ERROR )
1997-09-07 05:04:48 +00:00
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " SQL query to dump the contents of Table '%s' "
1997-09-07 05:04:48 +00:00
" did not execute. Explanation from backend: '%s'. \n "
" The query was: '%s'. \n " ,
classname , PQerrorMessage ( g_conn ) , query ) ;
exit_nicely ( g_conn ) ;
}
else
{
if ( PQresultStatus ( res ) ! = PGRES_COPY_OUT )
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " SQL query to dump the contents of Table '%s' "
1997-09-07 05:04:48 +00:00
" executed abnormally. \n "
" PQexec() returned status %d when %d was expected. \n "
" The query was: '%s'. \n " ,
classname , PQresultStatus ( res ) , PGRES_COPY_OUT , query ) ;
exit_nicely ( g_conn ) ;
}
else
{
copydone = false ;
while ( ! copydone )
{
1998-09-03 02:10:56 +00:00
ret = PQgetline ( g_conn , copybuf , COPYBUFSIZ ) ;
1997-09-07 05:04:48 +00:00
if ( copybuf [ 0 ] = = ' \\ ' & &
copybuf [ 1 ] = = ' . ' & &
copybuf [ 2 ] = = ' \0 ' )
{
copydone = true ; /* don't print this... */
}
else
{
fputs ( copybuf , fout ) ;
switch ( ret )
{
1997-09-08 02:41:22 +00:00
case EOF :
copydone = true ;
/* FALLTHROUGH */
case 0 :
fputc ( ' \n ' , fout ) ;
break ;
case 1 :
break ;
1997-09-07 05:04:48 +00:00
}
}
}
fprintf ( fout , " \\ . \n " ) ;
}
1998-09-03 02:10:56 +00:00
ret = PQendcopy ( g_conn ) ;
1997-09-07 05:04:48 +00:00
if ( ret ! = 0 )
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " SQL query to dump the contents of Table '%s' "
1997-09-07 05:04:48 +00:00
" did not execute correctly. After we read all the "
" table contents from the backend, PQendcopy() failed. "
" Explanation from backend: '%s'. \n "
" The query was: '%s'. \n " ,
classname , PQerrorMessage ( g_conn ) , query ) ;
1999-05-15 22:18:51 +00:00
PQclear ( res ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
}
1996-12-27 23:12:57 +00:00
}
static void
1999-12-11 00:31:05 +00:00
dumpClasses_dumpData ( FILE * fout , const char * classname )
1997-09-07 05:04:48 +00:00
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
PQExpBuffer q = createPQExpBuffer ( ) ;
1999-02-08 01:46:28 +00:00
int tuple ;
int field ;
1999-12-27 15:42:44 +00:00
const char * expsrc ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " SELECT * FROM %s " , fmtId ( classname , force_quotes ) ) ;
res = PQexec ( g_conn , q - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpClasses(): command failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
1999-02-08 01:46:28 +00:00
for ( tuple = 0 ; tuple < PQntuples ( res ) ; tuple + + )
1997-09-07 05:04:48 +00:00
{
1998-12-13 23:41:32 +00:00
fprintf ( fout , " INSERT INTO %s " , fmtId ( classname , force_quotes ) ) ;
1999-05-26 16:06:45 +00:00
if ( attrNames = = true )
1997-09-07 05:04:48 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " ( " ) ;
1999-02-08 01:46:28 +00:00
for ( field = 0 ; field < PQnfields ( res ) ; field + + )
1997-09-07 05:04:48 +00:00
{
1999-02-08 01:46:28 +00:00
if ( field > 0 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " , " ) ;
appendPQExpBuffer ( q , fmtId ( PQfname ( res , field ) , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
}
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ) " ) ;
fprintf ( fout , " %s " , q - > data ) ;
1997-09-07 05:04:48 +00:00
}
1999-05-26 21:51:13 +00:00
fprintf ( fout , " VALUES ( " ) ;
1999-02-08 01:46:28 +00:00
for ( field = 0 ; field < PQnfields ( res ) ; field + + )
1997-09-07 05:04:48 +00:00
{
1999-02-08 01:46:28 +00:00
if ( field > 0 )
fprintf ( fout , " , " ) ;
1997-09-07 05:04:48 +00:00
if ( PQgetisnull ( res , tuple , field ) )
1999-05-26 21:51:13 +00:00
{
1997-09-07 05:04:48 +00:00
fprintf ( fout , " NULL " ) ;
1999-05-26 21:51:13 +00:00
continue ;
}
switch ( PQftype ( res , field ) )
1997-09-07 05:04:48 +00:00
{
1999-05-26 21:51:13 +00:00
case INT2OID :
case INT4OID :
case OIDOID : /* int types */
case FLOAT4OID :
case FLOAT8OID : /* float types */
/* These types are printed without quotes */
fprintf ( fout , " %s " ,
PQgetvalue ( res , tuple , field ) ) ;
break ;
default :
/*
* All other types are printed as string literals ,
* with appropriate escaping of special
* characters . Quote mark ' goes to ' ' per SQL
* standard , other stuff goes to \ sequences .
*/
putc ( ' \' ' , fout ) ;
expsrc = PQgetvalue ( res , tuple , field ) ;
while ( * expsrc )
{
char ch = * expsrc + + ;
if ( ch = = ' \\ ' | | ch = = ' \' ' )
1997-09-08 02:41:22 +00:00
{
1999-05-26 21:51:13 +00:00
putc ( ch , fout ) ; /* double these */
putc ( ch , fout ) ;
1997-09-08 02:41:22 +00:00
}
1999-05-26 21:51:13 +00:00
else if ( ch < ' \040 ' )
{
/* generate octal escape for control chars */
putc ( ' \\ ' , fout ) ;
putc ( ( ( ch > > 6 ) & 3 ) + ' 0 ' , fout ) ;
putc ( ( ( ch > > 3 ) & 7 ) + ' 0 ' , fout ) ;
putc ( ( ch & 7 ) + ' 0 ' , fout ) ;
}
else
putc ( ch , fout ) ;
}
putc ( ' \' ' , fout ) ;
break ;
1997-09-07 05:04:48 +00:00
}
1999-02-08 01:46:28 +00:00
}
1997-09-07 05:04:48 +00:00
fprintf ( fout , " ); \n " ) ;
}
PQclear ( res ) ;
1996-12-27 23:12:57 +00:00
}
/*
* DumpClasses -
1997-09-07 05:04:48 +00:00
* dump the contents of all the classes .
1996-12-27 23:12:57 +00:00
*/
static void
1998-09-01 03:29:17 +00:00
dumpClasses ( const TableInfo * tblinfo , const int numTables , FILE * fout ,
1997-09-07 05:04:48 +00:00
const char * onlytable , const bool oids )
{
1997-09-08 02:41:22 +00:00
int i ;
1999-05-25 16:15:34 +00:00
char * all_only ;
1997-09-07 05:04:48 +00:00
if ( onlytable = = NULL )
all_only = " all " ;
else
1999-05-26 14:50:38 +00:00
all_only = " only " ;
1997-09-07 05:04:48 +00:00
if ( g_verbose )
1999-05-26 14:50:38 +00:00
fprintf ( stderr , " %s dumping out the contents of %s %d table%s/sequence%s %s \n " ,
g_comment_start , all_only ,
( onlytable = = NULL ) ? numTables : 1 ,
( onlytable = = NULL ) ? " s " : " " , ( onlytable = = NULL ) ? " s " : " " ,
g_comment_end ) ;
1998-02-26 04:46:47 +00:00
1997-10-02 13:57:07 +00:00
/* Dump SEQUENCEs first (if dataOnly) */
if ( dataOnly )
{
for ( i = 0 ; i < numTables ; i + + )
{
if ( ! ( tblinfo [ i ] . sequence ) )
continue ;
if ( ! onlytable | | ( ! strcmp ( tblinfo [ i ] . relname , onlytable ) ) )
{
if ( g_verbose )
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " %s dumping out schema of sequence '%s' %s \n " ,
1998-02-26 04:46:47 +00:00
g_comment_start , tblinfo [ i ] . relname , g_comment_end ) ;
1998-07-19 05:24:51 +00:00
becomeUser ( fout , tblinfo [ i ] . usename ) ;
1997-10-02 13:57:07 +00:00
dumpSequence ( fout , tblinfo [ i ] ) ;
}
}
}
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numTables ; i + + )
{
1997-09-08 02:41:22 +00:00
const char * classname = tblinfo [ i ] . relname ;
1997-09-07 05:04:48 +00:00
/* Skip VIEW relations */
if ( isViewRule ( tblinfo [ i ] . relname ) )
continue ;
1998-02-26 04:46:47 +00:00
if ( tblinfo [ i ] . sequence ) /* already dumped */
1997-10-02 13:57:07 +00:00
continue ;
1997-09-07 05:04:48 +00:00
if ( ! onlytable | | ( ! strcmp ( classname , onlytable ) ) )
{
if ( g_verbose )
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " %s dumping out the contents of Table '%s' %s \n " ,
1997-09-07 05:04:48 +00:00
g_comment_start , classname , g_comment_end ) ;
1998-07-19 05:24:51 +00:00
becomeUser ( fout , tblinfo [ i ] . usename ) ;
1997-09-07 05:04:48 +00:00
if ( ! dumpData )
dumpClasses_nodumpData ( fout , classname , oids ) ;
else
1999-12-11 00:31:05 +00:00
dumpClasses_dumpData ( fout , classname ) ;
1997-04-02 04:17:27 +00:00
}
1997-09-07 05:04:48 +00:00
}
1996-12-27 23:12:57 +00:00
}
1998-01-29 02:26:47 +00:00
static void
prompt_for_password ( char * username , char * password )
{
1998-09-20 03:18:43 +00:00
char buf [ 512 ] ;
1999-05-25 16:15:34 +00:00
int length ;
1998-01-29 02:26:47 +00:00
# ifdef HAVE_TERMIOS_H
1999-05-25 16:15:34 +00:00
struct termios t_orig ,
t ;
1998-01-29 02:26:47 +00:00
# endif
printf ( " Username: " ) ;
1998-09-20 03:18:43 +00:00
fgets ( username , 100 , stdin ) ;
1998-01-29 02:26:47 +00:00
length = strlen ( username ) ;
/* skip rest of the line */
if ( length > 0 & & username [ length - 1 ] ! = ' \n ' )
{
do
{
fgets ( buf , 512 , stdin ) ;
} while ( buf [ strlen ( buf ) - 1 ] ! = ' \n ' ) ;
}
if ( length > 0 & & username [ length - 1 ] = = ' \n ' )
username [ length - 1 ] = ' \0 ' ;
printf ( " Password: " ) ;
# ifdef HAVE_TERMIOS_H
tcgetattr ( 0 , & t ) ;
t_orig = t ;
t . c_lflag & = ~ ECHO ;
tcsetattr ( 0 , TCSADRAIN , & t ) ;
# endif
1998-09-20 03:18:43 +00:00
fgets ( password , 100 , stdin ) ;
1998-01-29 02:26:47 +00:00
# ifdef HAVE_TERMIOS_H
tcsetattr ( 0 , TCSADRAIN , & t_orig ) ;
# endif
length = strlen ( password ) ;
/* skip rest of the line */
if ( length > 0 & & password [ length - 1 ] ! = ' \n ' )
{
do
{
fgets ( buf , 512 , stdin ) ;
} while ( buf [ strlen ( buf ) - 1 ] ! = ' \n ' ) ;
}
if ( length > 0 & & password [ length - 1 ] = = ' \n ' )
password [ length - 1 ] = ' \0 ' ;
printf ( " \n \n " ) ;
}
1996-12-27 23:12:57 +00:00
1996-10-07 03:30:40 +00:00
int
1997-09-07 05:04:48 +00:00
main ( int argc , char * * argv )
1996-07-09 06:22:35 +00:00
{
1999-05-25 16:15:34 +00:00
int c ;
const char * progname ;
const char * filename = NULL ;
const char * dbname = NULL ;
const char * pghost = NULL ;
const char * pgport = NULL ;
char * tablename = NULL ;
1999-05-26 16:06:45 +00:00
bool oids = false ;
1999-05-25 16:15:34 +00:00
TableInfo * tblinfo ;
int numTables ;
1998-02-26 04:46:47 +00:00
char connect_string [ 512 ] = " " ;
char tmp_string [ 128 ] ;
1998-09-20 03:18:43 +00:00
char username [ 100 ] ;
char password [ 100 ] ;
1999-05-27 16:29:05 +00:00
bool use_password = false ;
1997-09-07 05:04:48 +00:00
1999-12-16 20:10:02 +00:00
# ifdef HAVE_GETOPT_LONG
static struct option long_options [ ] = {
{ " data-only " , no_argument , NULL , ' a ' } ,
{ " clean " , no_argument , NULL , ' c ' } ,
2000-01-18 00:03:37 +00:00
{ " inserts " , no_argument , NULL , ' d ' } ,
{ " attribute-inserts " , no_argument , NULL , ' D ' } ,
1999-12-16 20:10:02 +00:00
{ " host " , required_argument , NULL , ' h ' } ,
{ " no-quotes " , no_argument , NULL , ' n ' } ,
{ " quotes " , no_argument , NULL , ' N ' } ,
2000-01-24 19:34:19 +00:00
{ " oids " , no_argument , NULL , ' o ' } ,
1999-12-16 20:10:02 +00:00
{ " port " , required_argument , NULL , ' p ' } ,
{ " schema-only " , no_argument , NULL , ' s ' } ,
{ " table " , required_argument , NULL , ' t ' } ,
{ " password " , no_argument , NULL , ' u ' } ,
{ " verbose " , no_argument , NULL , ' v ' } ,
{ " no-acl " , no_argument , NULL , ' x ' } ,
{ " help " , no_argument , NULL , ' ? ' } ,
2000-01-18 00:03:37 +00:00
{ " version " , no_argument , NULL , ' V ' }
2000-01-10 17:14:46 +00:00
} ;
1999-12-16 20:10:02 +00:00
int optindex ;
# endif
1997-09-07 05:04:48 +00:00
g_verbose = false ;
1998-12-13 23:41:32 +00:00
force_quotes = true ;
1999-05-26 16:06:45 +00:00
dropSchema = false ;
1997-09-07 05:04:48 +00:00
strcpy ( g_comment_start , " -- " ) ;
g_comment_end [ 0 ] = ' \0 ' ;
strcpy ( g_opaque_type , " opaque " ) ;
1999-05-26 16:06:45 +00:00
dataOnly = schemaOnly = dumpData = attrNames = false ;
1997-09-07 05:04:48 +00:00
2000-01-18 00:03:37 +00:00
if ( ! strrchr ( argv [ 0 ] , SEP_CHAR ) )
progname = argv [ 0 ] ;
else
progname = strrchr ( argv [ 0 ] , SEP_CHAR ) + 1 ;
1997-09-07 05:04:48 +00:00
1999-12-16 20:10:02 +00:00
# ifdef HAVE_GETOPT_LONG
2000-01-24 19:34:19 +00:00
while ( ( c = getopt_long ( argc , argv , " acdDf:h:nNop:st:uvxzV? " , long_options , & optindex ) ) ! = - 1 )
1999-12-16 20:10:02 +00:00
# else
2000-01-24 19:34:19 +00:00
while ( ( c = getopt ( argc , argv , " acdDf:h:nNop:st:uvxzV?- " ) ) ! = - 1 )
1999-12-16 20:10:02 +00:00
# endif
1997-09-07 05:04:48 +00:00
{
switch ( c )
{
1997-12-01 21:01:24 +00:00
case ' a ' : /* Dump data only */
1999-05-26 16:06:45 +00:00
dataOnly = true ;
1997-12-01 21:01:24 +00:00
break ;
1999-05-25 16:15:34 +00:00
case ' c ' : /* clean (i.e., drop) schema prior to
* create */
1999-05-26 16:06:45 +00:00
dropSchema = true ;
1999-01-21 22:53:37 +00:00
break ;
1997-12-01 21:01:24 +00:00
case ' d ' : /* dump data as proper insert strings */
1999-05-26 16:06:45 +00:00
dumpData = true ;
1997-12-01 21:01:24 +00:00
break ;
case ' D ' : /* dump data as proper insert strings with
* attr names */
1999-05-26 16:06:45 +00:00
dumpData = true ;
attrNames = true ;
1997-12-01 21:01:24 +00:00
break ;
2000-01-19 02:59:03 +00:00
case ' f ' :
2000-02-02 13:20:15 +00:00
filename = optarg ;
break ;
1997-10-30 03:59:59 +00:00
case ' h ' : /* server host */
1997-09-08 02:41:22 +00:00
pghost = optarg ;
break ;
1999-05-25 16:15:34 +00:00
case ' n ' : /* Do not force double-quotes on
* identifiers */
1998-12-13 23:41:32 +00:00
force_quotes = false ;
1998-10-02 16:43:41 +00:00
break ;
1998-11-06 15:54:47 +00:00
case ' N ' : /* Force double-quotes on identifiers */
1998-12-13 23:41:32 +00:00
force_quotes = true ;
1998-11-06 15:54:47 +00:00
break ;
2000-01-24 19:34:19 +00:00
case ' o ' : /* Dump oids */
1999-05-26 16:06:45 +00:00
oids = true ;
1997-12-01 21:01:24 +00:00
break ;
1997-09-08 02:41:22 +00:00
case ' p ' : /* server port */
pgport = optarg ;
break ;
1997-12-01 21:01:24 +00:00
case ' s ' : /* dump schema only */
1999-05-26 16:06:45 +00:00
schemaOnly = true ;
1997-09-08 02:41:22 +00:00
break ;
case ' t ' : /* Dump data for this table only */
1998-02-18 15:33:37 +00:00
{
1998-02-26 04:46:47 +00:00
int i ;
1998-02-18 15:33:37 +00:00
tablename = strdup ( optarg ) ;
1999-05-25 16:15:34 +00:00
/*
* quoted string ? Then strip quotes and preserve
* case . . .
*/
1999-05-04 15:47:35 +00:00
if ( tablename [ 0 ] = = ' " ' )
{
strcpy ( tablename , & tablename [ 1 ] ) ;
1999-05-25 16:15:34 +00:00
if ( * ( tablename + strlen ( tablename ) - 1 ) = = ' " ' )
* ( tablename + strlen ( tablename ) - 1 ) = ' \0 ' ;
1999-05-04 15:47:35 +00:00
}
/* otherwise, convert table name to lowercase... */
else
{
for ( i = 0 ; tablename [ i ] ; i + + )
if ( isascii ( ( unsigned char ) tablename [ i ] ) & &
isupper ( tablename [ i ] ) )
tablename [ i ] = tolower ( tablename [ i ] ) ;
}
1998-02-18 15:33:37 +00:00
}
1997-09-08 02:41:22 +00:00
break ;
1999-05-27 16:29:05 +00:00
case ' u ' :
use_password = true ;
break ;
1997-12-01 21:01:24 +00:00
case ' v ' : /* verbose */
g_verbose = true ;
1997-09-08 02:41:22 +00:00
break ;
1999-05-27 16:29:05 +00:00
case ' x ' : /* skip ACL dump */
aclsSkip = true ;
1997-09-08 02:41:22 +00:00
break ;
2000-01-18 00:03:37 +00:00
case ' V ' :
version ( ) ;
exit ( 0 ) ;
break ;
2000-01-10 17:14:46 +00:00
case ' ? ' :
2000-01-19 02:59:03 +00:00
/* getopt returns '?' on unknown argument. That's not
quite what we want */
2000-01-29 16:58:54 +00:00
if ( strcmp ( argv [ optind - 1 ] , " -? " ) = = 0 | | strcmp ( argv [ optind - 1 ] , " --help " ) = = 0 )
2000-01-19 02:59:03 +00:00
{
help ( progname ) ;
exit ( 1 ) ;
}
else
{
fputs ( " Try -? for help. \n " , stderr ) ;
exit ( 1 ) ;
}
1997-09-08 02:41:22 +00:00
break ;
2000-01-19 02:59:03 +00:00
# ifndef HAVE_GETOPT_LONG
case ' - ' :
fprintf ( stderr , " %s was compiled without support for long options. \n "
" Use -? for help on invocation options. \n " , progname ) ;
exit ( 1 ) ;
break ;
# endif
2000-01-18 00:03:37 +00:00
default :
fprintf ( stderr , " %s: unknown option -%c \n Try -? for help. \n " , progname , c ) ;
exit ( 1 ) ;
1997-09-07 05:04:48 +00:00
}
}
1999-05-26 16:06:45 +00:00
if ( dumpData = = true & & oids = = true )
{
fprintf ( stderr ,
" %s: INSERT's can not set oids, so INSERT and OID options can not be used together. \n " ,
progname ) ;
2000-01-18 00:03:37 +00:00
exit ( 1 ) ;
1999-05-26 16:06:45 +00:00
}
2000-01-10 17:14:46 +00:00
1997-09-07 05:04:48 +00:00
/* open the output file */
if ( filename = = NULL )
g_fout = stdout ;
else
{
1999-01-17 06:20:06 +00:00
# ifndef __CYGWIN32__
1997-09-07 05:04:48 +00:00
g_fout = fopen ( filename , " w " ) ;
1999-01-17 06:20:06 +00:00
# else
g_fout = fopen ( filename , " wb " ) ;
# endif
1997-09-07 05:04:48 +00:00
if ( g_fout = = NULL )
{
fprintf ( stderr ,
" %s: could not open output file named %s for writing \n " ,
progname , filename ) ;
2000-01-18 00:03:37 +00:00
exit ( 1 ) ;
1997-09-07 05:04:48 +00:00
}
}
/* find database */
if ( ! ( dbname = argv [ optind ] ) & &
2000-01-18 00:03:37 +00:00
! ( dbname = getenv ( " PGDATABASE " ) ) )
1997-09-07 05:04:48 +00:00
{
fprintf ( stderr , " %s: no database name specified \n " , progname ) ;
2000-01-18 00:03:37 +00:00
exit ( 1 ) ;
1997-09-07 05:04:48 +00:00
}
1998-02-26 04:46:47 +00:00
/* g_conn = PQsetdb(pghost, pgport, NULL, NULL, dbname); */
if ( pghost ! = NULL )
{
sprintf ( tmp_string , " host=%s " , pghost ) ;
strcat ( connect_string , tmp_string ) ;
1998-01-29 02:26:47 +00:00
}
1998-02-26 04:46:47 +00:00
if ( pgport ! = NULL )
{
sprintf ( tmp_string , " port=%s " , pgport ) ;
strcat ( connect_string , tmp_string ) ;
1998-01-29 02:26:47 +00:00
}
1998-02-26 04:46:47 +00:00
if ( dbname ! = NULL )
{
sprintf ( tmp_string , " dbname=%s " , dbname ) ;
strcat ( connect_string , tmp_string ) ;
1998-01-29 02:26:47 +00:00
}
1998-02-26 04:46:47 +00:00
if ( use_password )
{
prompt_for_password ( username , password ) ;
strcat ( connect_string , " authtype=password " ) ;
sprintf ( tmp_string , " user=%s " , username ) ;
strcat ( connect_string , tmp_string ) ;
sprintf ( tmp_string , " password=%s " , password ) ;
strcat ( connect_string , tmp_string ) ;
1998-07-19 05:24:51 +00:00
MemSet ( tmp_string , 0 , sizeof ( tmp_string ) ) ;
MemSet ( password , 0 , sizeof ( password ) ) ;
1998-01-29 02:26:47 +00:00
}
g_conn = PQconnectdb ( connect_string ) ;
1998-07-19 05:24:51 +00:00
MemSet ( connect_string , 0 , sizeof ( connect_string ) ) ;
1997-09-07 05:04:48 +00:00
/* check to see that the backend connection was successfully made */
if ( PQstatus ( g_conn ) = = CONNECTION_BAD )
{
fprintf ( stderr , " Connection to database '%s' failed. \n " , dbname ) ;
fprintf ( stderr , " %s \n " , PQerrorMessage ( g_conn ) ) ;
exit_nicely ( g_conn ) ;
}
1999-05-29 10:25:33 +00:00
/*
* Start serializable transaction to dump consistent data
*/
{
PGresult * res ;
res = PQexec ( g_conn , " begin " ) ;
if ( ! res | | PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " BEGIN command failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
exit_nicely ( g_conn ) ;
}
PQclear ( res ) ;
res = PQexec ( g_conn , " set transaction isolation level serializable " ) ;
if ( ! res | | PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " SET TRANSACTION command failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
exit_nicely ( g_conn ) ;
}
PQclear ( res ) ;
}
1997-09-07 05:04:48 +00:00
g_last_builtin_oid = findLastBuiltinOid ( ) ;
1999-05-26 16:06:45 +00:00
if ( oids = = true )
1997-09-07 05:04:48 +00:00
setMaxOid ( g_fout ) ;
if ( ! dataOnly )
{
if ( g_verbose )
1999-05-10 00:46:32 +00:00
fprintf ( stderr , " %s last builtin oid is %u %s \n " ,
1997-09-07 05:04:48 +00:00
g_comment_start , g_last_builtin_oid , g_comment_end ) ;
1999-05-27 16:29:05 +00:00
tblinfo = dumpSchema ( g_fout , & numTables , tablename , aclsSkip ) ;
1997-09-07 05:04:48 +00:00
}
else
1999-05-27 16:29:05 +00:00
tblinfo = dumpSchema ( NULL , & numTables , tablename , aclsSkip ) ;
1997-09-07 05:04:48 +00:00
2000-02-07 16:30:58 +00:00
if ( ! schemaOnly ) {
if ( dataOnly )
fprintf ( g_fout , " UPDATE \" pg_class \" SET \" reltriggers \" = 0 WHERE \" relname \" !~ '^pg_'; \n " ) ;
1997-09-07 05:04:48 +00:00
dumpClasses ( tblinfo , numTables , g_fout , tablename , oids ) ;
2000-02-07 16:30:58 +00:00
if ( dataOnly ) {
fprintf ( g_fout , " BEGIN TRANSACTION; \n " ) ;
fprintf ( g_fout , " CREATE TEMP TABLE \" tr \" ( \" tmp_relname \" name, \" tmp_reltriggers \" smallint); \n " ) ;
fprintf ( g_fout , " INSERT INTO \" tr \" SELECT C. \" relname \" , count(T. \" oid \" ) FROM \" pg_class \" C, \" pg_trigger \" T WHERE C. \" oid \" = T. \" tgrelid \" AND C. \" relname \" !~ '^pg_' GROUP BY 1; \n " ) ;
fprintf ( g_fout , " UPDATE \" pg_class \" SET \" reltriggers \" = TMP. \" tmp_reltriggers \" FROM \" tr \" TMP WHERE \" pg_class \" . \" relname \" = TMP. \" tmp_relname \" ; \n " ) ;
fprintf ( g_fout , " COMMIT TRANSACTION; \n " ) ;
}
}
1998-02-26 04:46:47 +00:00
if ( ! dataOnly ) /* dump indexes and triggers at the end
* for performance */
1997-10-02 13:57:07 +00:00
{
dumpSchemaIdx ( g_fout , tablename , tblinfo , numTables ) ;
dumpTriggers ( g_fout , tablename , tblinfo , numTables ) ;
1998-10-06 22:14:21 +00:00
dumpRules ( g_fout , tablename , tblinfo , numTables ) ;
1997-10-02 13:57:07 +00:00
}
1997-09-07 05:04:48 +00:00
fflush ( g_fout ) ;
1999-05-26 21:51:13 +00:00
if ( g_fout ! = stdout )
fclose ( g_fout ) ;
1997-09-07 05:04:48 +00:00
clearTableInfo ( tblinfo , numTables ) ;
PQfinish ( g_conn ) ;
exit ( 0 ) ;
1996-07-09 06:22:35 +00:00
}
/*
1997-09-07 05:04:48 +00:00
* getTypes :
* read all base types in the system catalogs and return them in the
1996-07-09 06:22:35 +00:00
* TypeInfo * structure
*
1997-09-07 05:04:48 +00:00
* numTypes is set to the number of types read in
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
TypeInfo *
1996-07-09 06:22:35 +00:00
getTypes ( int * numTypes )
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
1999-05-25 16:15:34 +00:00
TypeInfo * tinfo ;
1997-09-08 02:41:22 +00:00
int i_oid ;
int i_typowner ;
int i_typname ;
int i_typlen ;
int i_typprtlen ;
int i_typinput ;
int i_typoutput ;
int i_typreceive ;
int i_typsend ;
int i_typelem ;
int i_typdelim ;
int i_typdefault ;
int i_typrelid ;
int i_typbyval ;
int i_usename ;
1997-09-07 05:04:48 +00:00
/* find all base types */
/*
* we include even the built - in types because those may be used as
* array elements by user - defined types
*/
/*
* we filter out the built - in types when we dump out the types
*/
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " SELECT pg_type.oid, typowner, typname, typlen, typprtlen, "
1997-09-07 05:04:48 +00:00
" typinput, typoutput, typreceive, typsend, typelem, typdelim, "
1999-12-27 15:42:44 +00:00
" typdefault, typrelid, typbyval, usename from pg_type, pg_user "
1997-09-07 05:04:48 +00:00
" where typowner = usesysid " ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTypes(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
tinfo = ( TypeInfo * ) malloc ( ntups * sizeof ( TypeInfo ) ) ;
i_oid = PQfnumber ( res , " oid " ) ;
i_typowner = PQfnumber ( res , " typowner " ) ;
i_typname = PQfnumber ( res , " typname " ) ;
i_typlen = PQfnumber ( res , " typlen " ) ;
i_typprtlen = PQfnumber ( res , " typprtlen " ) ;
i_typinput = PQfnumber ( res , " typinput " ) ;
i_typoutput = PQfnumber ( res , " typoutput " ) ;
i_typreceive = PQfnumber ( res , " typreceive " ) ;
i_typsend = PQfnumber ( res , " typsend " ) ;
i_typelem = PQfnumber ( res , " typelem " ) ;
i_typdelim = PQfnumber ( res , " typdelim " ) ;
i_typdefault = PQfnumber ( res , " typdefault " ) ;
i_typrelid = PQfnumber ( res , " typrelid " ) ;
i_typbyval = PQfnumber ( res , " typbyval " ) ;
i_usename = PQfnumber ( res , " usename " ) ;
for ( i = 0 ; i < ntups ; i + + )
{
tinfo [ i ] . oid = strdup ( PQgetvalue ( res , i , i_oid ) ) ;
tinfo [ i ] . typowner = strdup ( PQgetvalue ( res , i , i_typowner ) ) ;
tinfo [ i ] . typname = strdup ( PQgetvalue ( res , i , i_typname ) ) ;
tinfo [ i ] . typlen = strdup ( PQgetvalue ( res , i , i_typlen ) ) ;
tinfo [ i ] . typprtlen = strdup ( PQgetvalue ( res , i , i_typprtlen ) ) ;
tinfo [ i ] . typinput = strdup ( PQgetvalue ( res , i , i_typinput ) ) ;
tinfo [ i ] . typoutput = strdup ( PQgetvalue ( res , i , i_typoutput ) ) ;
tinfo [ i ] . typreceive = strdup ( PQgetvalue ( res , i , i_typreceive ) ) ;
tinfo [ i ] . typsend = strdup ( PQgetvalue ( res , i , i_typsend ) ) ;
tinfo [ i ] . typelem = strdup ( PQgetvalue ( res , i , i_typelem ) ) ;
tinfo [ i ] . typdelim = strdup ( PQgetvalue ( res , i , i_typdelim ) ) ;
tinfo [ i ] . typdefault = strdup ( PQgetvalue ( res , i , i_typdefault ) ) ;
tinfo [ i ] . typrelid = strdup ( PQgetvalue ( res , i , i_typrelid ) ) ;
tinfo [ i ] . usename = strdup ( PQgetvalue ( res , i , i_usename ) ) ;
if ( strcmp ( PQgetvalue ( res , i , i_typbyval ) , " f " ) = = 0 )
tinfo [ i ] . passedbyvalue = 0 ;
else
tinfo [ i ] . passedbyvalue = 1 ;
/*
* check for user - defined array types , omit system generated ones
*/
if ( ( strcmp ( tinfo [ i ] . typelem , " 0 " ) ! = 0 ) & &
tinfo [ i ] . typname [ 0 ] ! = ' _ ' )
tinfo [ i ] . isArray = 1 ;
else
tinfo [ i ] . isArray = 0 ;
}
* numTypes = ntups ;
PQclear ( res ) ;
return tinfo ;
1996-07-09 06:22:35 +00:00
}
/*
* getOperators :
1997-09-07 05:04:48 +00:00
* read all operators in the system catalogs and return them in the
1996-07-09 06:22:35 +00:00
* OprInfo * structure
*
1997-09-07 05:04:48 +00:00
* numOprs is set to the number of operators read in
*
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
OprInfo *
1996-07-09 06:22:35 +00:00
getOperators ( int * numOprs )
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
1997-09-08 02:41:22 +00:00
1999-05-25 16:15:34 +00:00
OprInfo * oprinfo ;
1997-09-08 02:41:22 +00:00
int i_oid ;
int i_oprname ;
int i_oprkind ;
int i_oprcode ;
int i_oprleft ;
int i_oprright ;
int i_oprcom ;
int i_oprnegate ;
int i_oprrest ;
int i_oprjoin ;
int i_oprcanhash ;
int i_oprlsortop ;
int i_oprrsortop ;
int i_usename ;
1997-09-07 05:04:48 +00:00
/*
* find all operators , including builtin operators , filter out
* system - defined operators at dump - out time
*/
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " SELECT pg_operator.oid, oprname, oprkind, oprcode, "
1997-09-07 05:04:48 +00:00
" oprleft, oprright, oprcom, oprnegate, oprrest, oprjoin, "
" oprcanhash, oprlsortop, oprrsortop, usename "
" from pg_operator, pg_user "
" where oprowner = usesysid " ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getOperators(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
* numOprs = ntups ;
oprinfo = ( OprInfo * ) malloc ( ntups * sizeof ( OprInfo ) ) ;
i_oid = PQfnumber ( res , " oid " ) ;
i_oprname = PQfnumber ( res , " oprname " ) ;
i_oprkind = PQfnumber ( res , " oprkind " ) ;
i_oprcode = PQfnumber ( res , " oprcode " ) ;
i_oprleft = PQfnumber ( res , " oprleft " ) ;
i_oprright = PQfnumber ( res , " oprright " ) ;
i_oprcom = PQfnumber ( res , " oprcom " ) ;
i_oprnegate = PQfnumber ( res , " oprnegate " ) ;
i_oprrest = PQfnumber ( res , " oprrest " ) ;
i_oprjoin = PQfnumber ( res , " oprjoin " ) ;
i_oprcanhash = PQfnumber ( res , " oprcanhash " ) ;
i_oprlsortop = PQfnumber ( res , " oprlsortop " ) ;
i_oprrsortop = PQfnumber ( res , " oprrsortop " ) ;
i_usename = PQfnumber ( res , " usename " ) ;
for ( i = 0 ; i < ntups ; i + + )
{
oprinfo [ i ] . oid = strdup ( PQgetvalue ( res , i , i_oid ) ) ;
oprinfo [ i ] . oprname = strdup ( PQgetvalue ( res , i , i_oprname ) ) ;
oprinfo [ i ] . oprkind = strdup ( PQgetvalue ( res , i , i_oprkind ) ) ;
oprinfo [ i ] . oprcode = strdup ( PQgetvalue ( res , i , i_oprcode ) ) ;
oprinfo [ i ] . oprleft = strdup ( PQgetvalue ( res , i , i_oprleft ) ) ;
oprinfo [ i ] . oprright = strdup ( PQgetvalue ( res , i , i_oprright ) ) ;
oprinfo [ i ] . oprcom = strdup ( PQgetvalue ( res , i , i_oprcom ) ) ;
oprinfo [ i ] . oprnegate = strdup ( PQgetvalue ( res , i , i_oprnegate ) ) ;
oprinfo [ i ] . oprrest = strdup ( PQgetvalue ( res , i , i_oprrest ) ) ;
oprinfo [ i ] . oprjoin = strdup ( PQgetvalue ( res , i , i_oprjoin ) ) ;
oprinfo [ i ] . oprcanhash = strdup ( PQgetvalue ( res , i , i_oprcanhash ) ) ;
oprinfo [ i ] . oprlsortop = strdup ( PQgetvalue ( res , i , i_oprlsortop ) ) ;
oprinfo [ i ] . oprrsortop = strdup ( PQgetvalue ( res , i , i_oprrsortop ) ) ;
oprinfo [ i ] . usename = strdup ( PQgetvalue ( res , i , i_usename ) ) ;
}
PQclear ( res ) ;
return oprinfo ;
1996-07-09 06:22:35 +00:00
}
1997-06-02 02:52:06 +00:00
void
1997-09-08 21:56:23 +00:00
clearTypeInfo ( TypeInfo * tp , int numTypes )
1997-06-02 02:52:06 +00:00
{
1997-09-08 02:41:22 +00:00
int i ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numTypes ; + + i )
{
if ( tp [ i ] . oid )
free ( tp [ i ] . oid ) ;
if ( tp [ i ] . typowner )
free ( tp [ i ] . typowner ) ;
if ( tp [ i ] . typname )
free ( tp [ i ] . typname ) ;
if ( tp [ i ] . typlen )
free ( tp [ i ] . typlen ) ;
if ( tp [ i ] . typprtlen )
free ( tp [ i ] . typprtlen ) ;
if ( tp [ i ] . typinput )
free ( tp [ i ] . typinput ) ;
if ( tp [ i ] . typoutput )
free ( tp [ i ] . typoutput ) ;
if ( tp [ i ] . typreceive )
free ( tp [ i ] . typreceive ) ;
if ( tp [ i ] . typsend )
free ( tp [ i ] . typsend ) ;
if ( tp [ i ] . typelem )
free ( tp [ i ] . typelem ) ;
if ( tp [ i ] . typdelim )
free ( tp [ i ] . typdelim ) ;
if ( tp [ i ] . typdefault )
free ( tp [ i ] . typdefault ) ;
if ( tp [ i ] . typrelid )
free ( tp [ i ] . typrelid ) ;
if ( tp [ i ] . usename )
free ( tp [ i ] . usename ) ;
}
free ( tp ) ;
1997-06-02 02:52:06 +00:00
}
void
1997-09-08 21:56:23 +00:00
clearFuncInfo ( FuncInfo * fun , int numFuncs )
1997-06-02 02:52:06 +00:00
{
1997-09-08 02:41:22 +00:00
int i ,
a ;
1997-09-07 05:04:48 +00:00
if ( ! fun )
return ;
for ( i = 0 ; i < numFuncs ; + + i )
{
if ( fun [ i ] . oid )
free ( fun [ i ] . oid ) ;
if ( fun [ i ] . proname )
free ( fun [ i ] . proname ) ;
if ( fun [ i ] . usename )
free ( fun [ i ] . usename ) ;
2000-01-10 17:14:46 +00:00
for ( a = 0 ; a < FUNC_MAX_ARGS ; + + a )
1997-09-07 05:04:48 +00:00
if ( fun [ i ] . argtypes [ a ] )
free ( fun [ i ] . argtypes [ a ] ) ;
if ( fun [ i ] . prorettype )
free ( fun [ i ] . prorettype ) ;
if ( fun [ i ] . prosrc )
free ( fun [ i ] . prosrc ) ;
if ( fun [ i ] . probin )
free ( fun [ i ] . probin ) ;
}
free ( fun ) ;
1997-06-02 02:52:06 +00:00
}
1997-08-19 21:40:56 +00:00
static void
1997-09-08 21:56:23 +00:00
clearTableInfo ( TableInfo * tblinfo , int numTables )
1997-06-02 02:52:06 +00:00
{
1997-09-08 02:41:22 +00:00
int i ,
j ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numTables ; + + i )
{
if ( tblinfo [ i ] . oid )
free ( tblinfo [ i ] . oid ) ;
if ( tblinfo [ i ] . relacl )
free ( tblinfo [ i ] . relacl ) ;
if ( tblinfo [ i ] . usename )
free ( tblinfo [ i ] . usename ) ;
if ( tblinfo [ i ] . relname )
free ( tblinfo [ i ] . relname ) ;
if ( tblinfo [ i ] . sequence )
continue ;
/* Process Attributes */
for ( j = 0 ; j < tblinfo [ i ] . numatts ; j + + )
{
2000-01-18 18:09:02 +00:00
if ( tblinfo [ i ] . attoids [ j ] )
free ( tblinfo [ i ] . attoids [ j ] ) ;
1997-09-07 05:04:48 +00:00
if ( tblinfo [ i ] . attnames [ j ] )
free ( tblinfo [ i ] . attnames [ j ] ) ;
if ( tblinfo [ i ] . typnames [ j ] )
free ( tblinfo [ i ] . typnames [ j ] ) ;
}
1998-01-16 23:21:07 +00:00
if ( tblinfo [ i ] . atttypmod )
free ( ( int * ) tblinfo [ i ] . atttypmod ) ;
1997-09-07 05:04:48 +00:00
if ( tblinfo [ i ] . inhAttrs )
free ( ( int * ) tblinfo [ i ] . inhAttrs ) ;
if ( tblinfo [ i ] . attnames )
free ( tblinfo [ i ] . attnames ) ;
if ( tblinfo [ i ] . typnames )
free ( tblinfo [ i ] . typnames ) ;
if ( tblinfo [ i ] . notnull )
free ( tblinfo [ i ] . notnull ) ;
2000-01-10 17:14:46 +00:00
if ( tblinfo [ i ] . primary_key )
free ( tblinfo [ i ] . primary_key ) ;
1997-09-07 05:04:48 +00:00
}
free ( tblinfo ) ;
1997-06-02 02:52:06 +00:00
}
1997-09-07 05:04:48 +00:00
void
1997-09-08 21:56:23 +00:00
clearInhInfo ( InhInfo * inh , int numInherits )
1997-09-07 05:04:48 +00:00
{
1997-09-08 02:41:22 +00:00
int i ;
1997-09-07 05:04:48 +00:00
if ( ! inh )
return ;
for ( i = 0 ; i < numInherits ; + + i )
{
1999-11-22 17:56:41 +00:00
if ( inh [ i ] . inhrelid )
free ( inh [ i ] . inhrelid ) ;
1997-09-07 05:04:48 +00:00
if ( inh [ i ] . inhparent )
free ( inh [ i ] . inhparent ) ;
}
free ( inh ) ;
1997-06-02 02:52:06 +00:00
}
void
1997-09-08 21:56:23 +00:00
clearOprInfo ( OprInfo * opr , int numOprs )
1997-09-07 05:04:48 +00:00
{
1997-09-08 02:41:22 +00:00
int i ;
1997-09-07 05:04:48 +00:00
if ( ! opr )
return ;
for ( i = 0 ; i < numOprs ; + + i )
{
if ( opr [ i ] . oid )
free ( opr [ i ] . oid ) ;
if ( opr [ i ] . oprname )
free ( opr [ i ] . oprname ) ;
if ( opr [ i ] . oprkind )
free ( opr [ i ] . oprkind ) ;
if ( opr [ i ] . oprcode )
free ( opr [ i ] . oprcode ) ;
if ( opr [ i ] . oprleft )
free ( opr [ i ] . oprleft ) ;
if ( opr [ i ] . oprright )
free ( opr [ i ] . oprright ) ;
if ( opr [ i ] . oprcom )
free ( opr [ i ] . oprcom ) ;
if ( opr [ i ] . oprnegate )
free ( opr [ i ] . oprnegate ) ;
if ( opr [ i ] . oprrest )
free ( opr [ i ] . oprrest ) ;
if ( opr [ i ] . oprjoin )
free ( opr [ i ] . oprjoin ) ;
if ( opr [ i ] . oprcanhash )
free ( opr [ i ] . oprcanhash ) ;
if ( opr [ i ] . oprlsortop )
free ( opr [ i ] . oprlsortop ) ;
if ( opr [ i ] . oprrsortop )
free ( opr [ i ] . oprrsortop ) ;
if ( opr [ i ] . usename )
free ( opr [ i ] . usename ) ;
}
free ( opr ) ;
1997-06-02 02:52:06 +00:00
}
void
1997-09-08 21:56:23 +00:00
clearIndInfo ( IndInfo * ind , int numIndices )
1997-06-02 02:52:06 +00:00
{
1997-09-08 02:41:22 +00:00
int i ,
a ;
1997-09-07 05:04:48 +00:00
if ( ! ind )
return ;
for ( i = 0 ; i < numIndices ; + + i )
{
2000-01-18 18:09:02 +00:00
if ( ind [ i ] . indoid )
free ( ind [ i ] . indoid ) ;
1997-09-07 05:04:48 +00:00
if ( ind [ i ] . indexrelname )
free ( ind [ i ] . indexrelname ) ;
if ( ind [ i ] . indrelname )
free ( ind [ i ] . indrelname ) ;
if ( ind [ i ] . indamname )
free ( ind [ i ] . indamname ) ;
if ( ind [ i ] . indproc )
free ( ind [ i ] . indproc ) ;
if ( ind [ i ] . indisunique )
free ( ind [ i ] . indisunique ) ;
for ( a = 0 ; a < INDEX_MAX_KEYS ; + + a )
{
if ( ind [ i ] . indkey [ a ] )
free ( ind [ i ] . indkey [ a ] ) ;
if ( ind [ i ] . indclass [ a ] )
free ( ind [ i ] . indclass [ a ] ) ;
}
}
free ( ind ) ;
1997-06-02 02:52:06 +00:00
}
void
1997-09-08 20:59:27 +00:00
clearAggInfo ( AggInfo * agginfo , int numArgs )
1997-06-02 02:52:06 +00:00
{
1997-09-08 02:41:22 +00:00
int i ;
1997-09-07 05:04:48 +00:00
if ( ! agginfo )
return ;
for ( i = 0 ; i < numArgs ; + + i )
{
if ( agginfo [ i ] . oid )
free ( agginfo [ i ] . oid ) ;
if ( agginfo [ i ] . aggname )
free ( agginfo [ i ] . aggname ) ;
if ( agginfo [ i ] . aggtransfn1 )
free ( agginfo [ i ] . aggtransfn1 ) ;
if ( agginfo [ i ] . aggtransfn2 )
free ( agginfo [ i ] . aggtransfn2 ) ;
if ( agginfo [ i ] . aggfinalfn )
free ( agginfo [ i ] . aggfinalfn ) ;
if ( agginfo [ i ] . aggtranstype1 )
free ( agginfo [ i ] . aggtranstype1 ) ;
if ( agginfo [ i ] . aggbasetype )
free ( agginfo [ i ] . aggbasetype ) ;
if ( agginfo [ i ] . aggtranstype2 )
free ( agginfo [ i ] . aggtranstype2 ) ;
if ( agginfo [ i ] . agginitval1 )
free ( agginfo [ i ] . agginitval1 ) ;
if ( agginfo [ i ] . agginitval2 )
free ( agginfo [ i ] . agginitval2 ) ;
if ( agginfo [ i ] . usename )
free ( agginfo [ i ] . usename ) ;
}
free ( agginfo ) ;
1997-06-02 02:52:06 +00:00
}
1996-07-09 06:22:35 +00:00
/*
* getAggregates :
1997-09-07 05:04:48 +00:00
* read all the user - defined aggregates in the system catalogs and
1996-07-09 06:22:35 +00:00
* return them in the AggInfo * structure
*
1997-09-07 05:04:48 +00:00
* numAggs is set to the number of aggregates read in
*
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
AggInfo *
1996-07-09 06:22:35 +00:00
getAggregates ( int * numAggs )
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
1999-05-25 16:15:34 +00:00
AggInfo * agginfo ;
1997-09-08 02:41:22 +00:00
int i_oid ;
int i_aggname ;
int i_aggtransfn1 ;
int i_aggtransfn2 ;
int i_aggfinalfn ;
int i_aggtranstype1 ;
int i_aggbasetype ;
int i_aggtranstype2 ;
int i_agginitval1 ;
int i_agginitval2 ;
int i_usename ;
1997-09-07 05:04:48 +00:00
/* find all user-defined aggregates */
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query ,
1997-09-07 05:04:48 +00:00
" SELECT pg_aggregate.oid, aggname, aggtransfn1, aggtransfn2, "
" aggfinalfn, aggtranstype1, aggbasetype, aggtranstype2, "
" agginitval1, agginitval2, usename from pg_aggregate, pg_user "
" where aggowner = usesysid " ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getAggregates(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
* numAggs = ntups ;
agginfo = ( AggInfo * ) malloc ( ntups * sizeof ( AggInfo ) ) ;
i_oid = PQfnumber ( res , " oid " ) ;
i_aggname = PQfnumber ( res , " aggname " ) ;
i_aggtransfn1 = PQfnumber ( res , " aggtransfn1 " ) ;
i_aggtransfn2 = PQfnumber ( res , " aggtransfn2 " ) ;
i_aggfinalfn = PQfnumber ( res , " aggfinalfn " ) ;
i_aggtranstype1 = PQfnumber ( res , " aggtranstype1 " ) ;
i_aggbasetype = PQfnumber ( res , " aggbasetype " ) ;
i_aggtranstype2 = PQfnumber ( res , " aggtranstype2 " ) ;
i_agginitval1 = PQfnumber ( res , " agginitval1 " ) ;
i_agginitval2 = PQfnumber ( res , " agginitval2 " ) ;
i_usename = PQfnumber ( res , " usename " ) ;
for ( i = 0 ; i < ntups ; i + + )
{
agginfo [ i ] . oid = strdup ( PQgetvalue ( res , i , i_oid ) ) ;
agginfo [ i ] . aggname = strdup ( PQgetvalue ( res , i , i_aggname ) ) ;
agginfo [ i ] . aggtransfn1 = strdup ( PQgetvalue ( res , i , i_aggtransfn1 ) ) ;
agginfo [ i ] . aggtransfn2 = strdup ( PQgetvalue ( res , i , i_aggtransfn2 ) ) ;
agginfo [ i ] . aggfinalfn = strdup ( PQgetvalue ( res , i , i_aggfinalfn ) ) ;
agginfo [ i ] . aggtranstype1 = strdup ( PQgetvalue ( res , i , i_aggtranstype1 ) ) ;
agginfo [ i ] . aggbasetype = strdup ( PQgetvalue ( res , i , i_aggbasetype ) ) ;
agginfo [ i ] . aggtranstype2 = strdup ( PQgetvalue ( res , i , i_aggtranstype2 ) ) ;
agginfo [ i ] . agginitval1 = strdup ( PQgetvalue ( res , i , i_agginitval1 ) ) ;
agginfo [ i ] . agginitval2 = strdup ( PQgetvalue ( res , i , i_agginitval2 ) ) ;
agginfo [ i ] . usename = strdup ( PQgetvalue ( res , i , i_usename ) ) ;
}
PQclear ( res ) ;
return agginfo ;
1996-07-09 06:22:35 +00:00
}
/*
* getFuncs :
1997-09-07 05:04:48 +00:00
* read all the user - defined functions in the system catalogs and
1996-07-09 06:22:35 +00:00
* return them in the FuncInfo * structure
*
1997-09-07 05:04:48 +00:00
* numFuncs is set to the number of functions read in
*
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
FuncInfo *
1996-07-09 06:22:35 +00:00
getFuncs ( int * numFuncs )
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
FuncInfo * finfo ;
1997-09-08 02:41:22 +00:00
int i_oid ;
int i_proname ;
int i_prolang ;
int i_pronargs ;
int i_proargtypes ;
int i_prorettype ;
int i_proretset ;
int i_prosrc ;
int i_probin ;
int i_usename ;
1997-09-07 05:04:48 +00:00
/* find all user-defined funcs */
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query ,
1997-09-07 05:04:48 +00:00
" SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
" proretset, proargtypes, prosrc, probin, usename "
" from pg_proc, pg_user "
1999-05-10 00:46:32 +00:00
" where pg_proc.oid > '%u'::oid and proowner = usesysid " ,
1997-09-07 05:04:48 +00:00
g_last_builtin_oid ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getFuncs(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
* numFuncs = ntups ;
finfo = ( FuncInfo * ) malloc ( ntups * sizeof ( FuncInfo ) ) ;
2000-01-16 03:54:58 +00:00
memset ( ( char * ) finfo , 0 , ntups * sizeof ( FuncInfo ) ) ;
1997-09-07 05:04:48 +00:00
i_oid = PQfnumber ( res , " oid " ) ;
i_proname = PQfnumber ( res , " proname " ) ;
i_prolang = PQfnumber ( res , " prolang " ) ;
i_pronargs = PQfnumber ( res , " pronargs " ) ;
i_proargtypes = PQfnumber ( res , " proargtypes " ) ;
i_prorettype = PQfnumber ( res , " prorettype " ) ;
i_proretset = PQfnumber ( res , " proretset " ) ;
i_prosrc = PQfnumber ( res , " prosrc " ) ;
i_probin = PQfnumber ( res , " probin " ) ;
i_usename = PQfnumber ( res , " usename " ) ;
for ( i = 0 ; i < ntups ; i + + )
{
finfo [ i ] . oid = strdup ( PQgetvalue ( res , i , i_oid ) ) ;
finfo [ i ] . proname = strdup ( PQgetvalue ( res , i , i_proname ) ) ;
finfo [ i ] . prosrc = checkForQuote ( PQgetvalue ( res , i , i_prosrc ) ) ;
finfo [ i ] . probin = strdup ( PQgetvalue ( res , i , i_probin ) ) ;
finfo [ i ] . prorettype = strdup ( PQgetvalue ( res , i , i_prorettype ) ) ;
finfo [ i ] . retset = ( strcmp ( PQgetvalue ( res , i , i_proretset ) , " t " ) = = 0 ) ;
finfo [ i ] . nargs = atoi ( PQgetvalue ( res , i , i_pronargs ) ) ;
1997-09-24 15:36:36 +00:00
finfo [ i ] . lang = atoi ( PQgetvalue ( res , i , i_prolang ) ) ;
1997-09-07 05:04:48 +00:00
finfo [ i ] . usename = strdup ( PQgetvalue ( res , i , i_usename ) ) ;
2000-01-16 03:54:58 +00:00
if ( finfo [ i ] . nargs < 0 | | finfo [ i ] . nargs > FUNC_MAX_ARGS )
{
fprintf ( stderr , " failed sanity check: %s has %d args \n " ,
finfo [ i ] . proname , finfo [ i ] . nargs ) ;
2000-01-18 00:03:37 +00:00
exit ( 1 ) ;
2000-01-16 03:54:58 +00:00
}
parseNumericArray ( PQgetvalue ( res , i , i_proargtypes ) ,
finfo [ i ] . argtypes ,
finfo [ i ] . nargs ) ;
1997-09-07 05:04:48 +00:00
finfo [ i ] . dumped = 0 ;
}
PQclear ( res ) ;
return finfo ;
1996-07-09 06:22:35 +00:00
}
/*
* getTables
1997-09-07 05:04:48 +00:00
* read all the user - defined tables ( no indices , no catalogs )
1996-07-09 06:22:35 +00:00
* in the system catalogs return them in the TableInfo * structure
*
1997-09-07 05:04:48 +00:00
* numTables is set to the number of tables read in
*
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
TableInfo *
1997-10-02 13:57:07 +00:00
getTables ( int * numTables , FuncInfo * finfo , int numFuncs )
1996-07-09 06:22:35 +00:00
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
TableInfo * tblinfo ;
1997-09-08 02:41:22 +00:00
int i_oid ;
int i_relname ;
int i_relkind ;
int i_relacl ;
int i_usename ;
1997-10-02 13:57:07 +00:00
int i_relchecks ;
int i_reltriggers ;
1999-12-11 00:31:05 +00:00
int i_relhasindex ;
1997-09-07 05:04:48 +00:00
/*
* find all the user - defined tables ( no indices and no catalogs ) ,
* ordering by oid is important so that we always process the parent
* tables before the child tables when traversing the tblinfo *
*
1999-06-03 04:01:16 +00:00
* we ignore tables that are not type ' r ' ( ordinary relation )
* or ' S ' ( sequence ) - - - in particular , Large Object relations
* ( type ' l ' ) are ignored .
1997-09-07 05:04:48 +00:00
*/
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query ,
1998-02-26 04:46:47 +00:00
" SELECT pg_class.oid, relname, relkind, relacl, usename, "
1999-12-11 00:31:05 +00:00
" relchecks, reltriggers, relhasindex "
1997-09-07 05:04:48 +00:00
" from pg_class, pg_user "
" where relowner = usesysid and "
" (relkind = 'r' or relkind = 'S') and relname !~ '^pg_' "
1998-08-06 05:13:14 +00:00
" order by oid " ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTables(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
* numTables = ntups ;
tblinfo = ( TableInfo * ) malloc ( ntups * sizeof ( TableInfo ) ) ;
i_oid = PQfnumber ( res , " oid " ) ;
i_relname = PQfnumber ( res , " relname " ) ;
i_relkind = PQfnumber ( res , " relkind " ) ;
i_relacl = PQfnumber ( res , " relacl " ) ;
i_usename = PQfnumber ( res , " usename " ) ;
1997-10-02 13:57:07 +00:00
i_relchecks = PQfnumber ( res , " relchecks " ) ;
i_reltriggers = PQfnumber ( res , " reltriggers " ) ;
1999-12-27 15:42:44 +00:00
i_relhasindex = PQfnumber ( res , " relhasindex " ) ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < ntups ; i + + )
{
tblinfo [ i ] . oid = strdup ( PQgetvalue ( res , i , i_oid ) ) ;
tblinfo [ i ] . relname = strdup ( PQgetvalue ( res , i , i_relname ) ) ;
tblinfo [ i ] . relacl = strdup ( PQgetvalue ( res , i , i_relacl ) ) ;
tblinfo [ i ] . sequence = ( strcmp ( PQgetvalue ( res , i , i_relkind ) , " S " ) = = 0 ) ;
tblinfo [ i ] . usename = strdup ( PQgetvalue ( res , i , i_usename ) ) ;
1997-10-02 13:57:07 +00:00
tblinfo [ i ] . ncheck = atoi ( PQgetvalue ( res , i , i_relchecks ) ) ;
tblinfo [ i ] . ntrig = atoi ( PQgetvalue ( res , i , i_reltriggers ) ) ;
1998-02-26 04:46:47 +00:00
1999-05-25 16:15:34 +00:00
/*
* Exclude inherited CHECKs from CHECK constraints total . If a
* constraint matches by name and condition with a constraint
1998-12-05 22:09:57 +00:00
* belonging to a parent class , we assume it was inherited .
*/
if ( tblinfo [ i ] . ncheck > 0 )
{
1999-05-25 16:15:34 +00:00
PGresult * res2 ;
1998-12-05 22:09:57 +00:00
int ntups2 ;
1999-05-25 16:15:34 +00:00
if ( g_verbose )
1998-12-05 22:09:57 +00:00
fprintf ( stderr , " %s excluding inherited CHECK constraints "
" for relation: '%s' %s \n " ,
g_comment_start ,
tblinfo [ i ] . relname ,
g_comment_end ) ;
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " SELECT rcname from pg_relcheck, pg_inherits as i "
1998-12-05 22:09:57 +00:00
" where rcrelid = '%s'::oid "
1999-11-22 17:56:41 +00:00
" and rcrelid = i.inhrelid "
1998-12-05 22:09:57 +00:00
" and exists "
" (select * from pg_relcheck as c "
" where c.rcname = pg_relcheck.rcname "
" and c.rcsrc = pg_relcheck.rcsrc "
" and c.rcrelid = i.inhparent) " ,
tblinfo [ i ] . oid ) ;
1999-12-27 15:42:44 +00:00
res2 = PQexec ( g_conn , query - > data ) ;
1998-12-05 22:09:57 +00:00
if ( ! res2 | |
PQresultStatus ( res2 ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTables(): SELECT (for inherited CHECK) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1998-12-05 22:09:57 +00:00
exit_nicely ( g_conn ) ;
}
ntups2 = PQntuples ( res2 ) ;
tblinfo [ i ] . ncheck - = ntups2 ;
if ( tblinfo [ i ] . ncheck < 0 )
{
fprintf ( stderr , " getTables(): found more inherited CHECKs than total for "
" relation %s \n " ,
tblinfo [ i ] . relname ) ;
exit_nicely ( g_conn ) ;
}
PQclear ( res2 ) ;
}
/* Get non-inherited CHECK constraints, if any */
1997-10-02 13:57:07 +00:00
if ( tblinfo [ i ] . ncheck > 0 )
{
PGresult * res2 ;
1998-02-26 04:46:47 +00:00
int i_rcname ,
i_rcsrc ;
1997-10-02 13:57:07 +00:00
int ntups2 ;
int i2 ;
1998-02-26 04:46:47 +00:00
1997-10-02 13:57:07 +00:00
if ( g_verbose )
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " %s finding CHECK constraints for relation: '%s' %s \n " ,
1997-10-02 13:57:07 +00:00
g_comment_start ,
tblinfo [ i ] . relname ,
g_comment_end ) ;
1998-02-26 04:46:47 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " SELECT rcname, rcsrc from pg_relcheck "
1998-12-05 22:09:57 +00:00
" where rcrelid = '%s'::oid "
" and not exists "
" (select * from pg_relcheck as c, pg_inherits as i "
1999-11-22 17:56:41 +00:00
" where i.inhrelid = pg_relcheck.rcrelid "
1998-12-05 22:09:57 +00:00
" and c.rcname = pg_relcheck.rcname "
" and c.rcsrc = pg_relcheck.rcsrc "
" and c.rcrelid = i.inhparent) " ,
1997-10-02 13:57:07 +00:00
tblinfo [ i ] . oid ) ;
1999-12-27 15:42:44 +00:00
res2 = PQexec ( g_conn , query - > data ) ;
1997-10-02 13:57:07 +00:00
if ( ! res2 | |
1998-02-26 04:46:47 +00:00
PQresultStatus ( res2 ) ! = PGRES_TUPLES_OK )
1997-10-02 13:57:07 +00:00
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTables(): SELECT (for CHECK) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-10-02 13:57:07 +00:00
exit_nicely ( g_conn ) ;
}
ntups2 = PQntuples ( res2 ) ;
if ( ntups2 ! = tblinfo [ i ] . ncheck )
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " getTables(): relation '%s': %d CHECKs were expected, but got %d \n " ,
1998-02-26 04:46:47 +00:00
tblinfo [ i ] . relname , tblinfo [ i ] . ncheck , ntups2 ) ;
1997-10-02 13:57:07 +00:00
exit_nicely ( g_conn ) ;
}
i_rcname = PQfnumber ( res2 , " rcname " ) ;
i_rcsrc = PQfnumber ( res2 , " rcsrc " ) ;
1998-02-26 04:46:47 +00:00
tblinfo [ i ] . check_expr = ( char * * ) malloc ( ntups2 * sizeof ( char * ) ) ;
1997-10-02 13:57:07 +00:00
for ( i2 = 0 ; i2 < ntups2 ; i2 + + )
{
1999-12-11 00:31:05 +00:00
const char * name = PQgetvalue ( res2 , i2 , i_rcname ) ;
const char * expr = PQgetvalue ( res2 , i2 , i_rcsrc ) ;
1998-02-26 04:46:47 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
1999-12-27 18:21:07 +00:00
if ( name [ 0 ] ! = ' $ ' ) {
2000-01-18 07:29:58 +00:00
appendPQExpBuffer ( query , " CONSTRAINT %s " ,
fmtId ( name , force_quotes ) ) ;
1999-12-27 18:21:07 +00:00
}
2000-01-18 07:29:58 +00:00
appendPQExpBuffer ( query , " CHECK (%s) " , expr ) ;
1999-12-27 15:42:44 +00:00
tblinfo [ i ] . check_expr [ i2 ] = strdup ( query - > data ) ;
1997-10-02 13:57:07 +00:00
}
PQclear ( res2 ) ;
}
else
tblinfo [ i ] . check_expr = NULL ;
1998-02-26 04:46:47 +00:00
2000-01-10 17:14:46 +00:00
/* Get primary key */
2000-01-18 07:29:58 +00:00
if ( strcmp ( PQgetvalue ( res , i , i_relhasindex ) , " t " ) = = 0 )
{
PGresult * res2 ;
char str [ INDEX_MAX_KEYS * ( NAMEDATALEN * 2 + 4 ) + 1 ] ;
int j ;
1999-12-11 00:31:05 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
1999-12-27 18:21:07 +00:00
appendPQExpBuffer ( query ,
2000-01-10 17:14:46 +00:00
" SELECT a.attname "
" FROM pg_index i, pg_class c, pg_attribute a "
" WHERE i.indisprimary AND i.indrelid = %s "
" AND i.indexrelid = c.oid AND a.attnum > 0 AND a.attrelid = c.oid "
" ORDER BY a.attnum " ,
tblinfo [ i ] . oid ) ;
2000-01-18 07:29:58 +00:00
res2 = PQexec ( g_conn , query - > data ) ;
1999-12-11 00:31:05 +00:00
if ( ! res2 | | PQresultStatus ( res2 ) ! = PGRES_TUPLES_OK )
{
fprintf ( stderr , " getTables(): SELECT (for PRIMARY KEY) failed. Explanation from backend: %s " ,
2000-01-10 17:14:46 +00:00
PQerrorMessage ( g_conn ) ) ;
1999-12-11 00:31:05 +00:00
exit_nicely ( g_conn ) ;
}
2000-01-10 17:14:46 +00:00
2000-01-18 07:29:58 +00:00
str [ 0 ] = ' \0 ' ;
for ( j = 0 ; j < PQntuples ( res2 ) ; j + + )
{
if ( strlen ( str ) > 0 )
strcat ( str , " , " ) ;
strcat ( str , fmtId ( PQgetvalue ( res2 , j , 0 ) , force_quotes ) ) ;
}
if ( strlen ( str ) > 0 ) {
tblinfo [ i ] . primary_key = strdup ( str ) ;
if ( tblinfo [ i ] . primary_key = = NULL ) {
perror ( " strdup " ) ;
exit ( 1 ) ;
}
}
else
tblinfo [ i ] . primary_key = NULL ;
2000-01-10 17:14:46 +00:00
}
2000-01-18 07:29:58 +00:00
else
tblinfo [ i ] . primary_key = NULL ;
1999-12-11 00:31:05 +00:00
1997-10-02 13:57:07 +00:00
/* Get Triggers */
if ( tblinfo [ i ] . ntrig > 0 )
{
PGresult * res2 ;
2000-01-18 18:09:02 +00:00
int i_tgoid ,
i_tgname ,
1998-02-26 04:46:47 +00:00
i_tgfoid ,
i_tgtype ,
i_tgnargs ,
2000-02-04 18:49:34 +00:00
i_tgargs ,
i_tgisconstraint ,
i_tgconstrname ,
i_tgdeferrable ,
i_tginitdeferred ;
1997-10-02 13:57:07 +00:00
int ntups2 ;
int i2 ;
1998-02-26 04:46:47 +00:00
1997-10-02 13:57:07 +00:00
if ( g_verbose )
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " %s finding Triggers for relation: '%s' %s \n " ,
1997-10-02 13:57:07 +00:00
g_comment_start ,
tblinfo [ i ] . relname ,
g_comment_end ) ;
1998-02-26 04:46:47 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
2000-02-04 18:49:34 +00:00
appendPQExpBuffer ( query , " SELECT tgname, tgfoid, tgtype, tgnargs, tgargs, tgisconstraint, tgconstrname, tgdeferrable, tginitdeferred, oid "
1997-10-02 13:57:07 +00:00
" from pg_trigger "
" where tgrelid = '%s'::oid " ,
tblinfo [ i ] . oid ) ;
1999-12-27 15:42:44 +00:00
res2 = PQexec ( g_conn , query - > data ) ;
1997-10-02 13:57:07 +00:00
if ( ! res2 | |
1998-02-26 04:46:47 +00:00
PQresultStatus ( res2 ) ! = PGRES_TUPLES_OK )
1997-10-02 13:57:07 +00:00
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTables(): SELECT (for TRIGGER) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-10-02 13:57:07 +00:00
exit_nicely ( g_conn ) ;
}
ntups2 = PQntuples ( res2 ) ;
if ( ntups2 ! = tblinfo [ i ] . ntrig )
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " getTables(): relation '%s': %d Triggers were expected, but got %d \n " ,
1998-02-26 04:46:47 +00:00
tblinfo [ i ] . relname , tblinfo [ i ] . ntrig , ntups2 ) ;
1997-10-02 13:57:07 +00:00
exit_nicely ( g_conn ) ;
}
i_tgname = PQfnumber ( res2 , " tgname " ) ;
i_tgfoid = PQfnumber ( res2 , " tgfoid " ) ;
i_tgtype = PQfnumber ( res2 , " tgtype " ) ;
i_tgnargs = PQfnumber ( res2 , " tgnargs " ) ;
i_tgargs = PQfnumber ( res2 , " tgargs " ) ;
2000-01-18 18:09:02 +00:00
i_tgoid = PQfnumber ( res2 , " oid " ) ;
2000-02-04 18:49:34 +00:00
i_tgisconstraint = PQfnumber ( res2 , " tgisconstraint " ) ;
i_tgconstrname = PQfnumber ( res2 , " tgconstrname " ) ;
i_tgdeferrable = PQfnumber ( res2 , " tgdeferrable " ) ;
i_tginitdeferred = PQfnumber ( res2 , " tginitdeferred " ) ;
1998-02-26 04:46:47 +00:00
tblinfo [ i ] . triggers = ( char * * ) malloc ( ntups2 * sizeof ( char * ) ) ;
2000-01-18 18:09:02 +00:00
tblinfo [ i ] . trcomments = ( char * * ) malloc ( ntups2 * sizeof ( char * ) ) ;
tblinfo [ i ] . troids = ( char * * ) malloc ( ntups2 * sizeof ( char * ) ) ;
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
for ( i2 = 0 ; i2 < ntups2 ; i2 + + )
1997-10-02 13:57:07 +00:00
{
2000-02-04 18:49:34 +00:00
const char * tgfuncoid = PQgetvalue ( res2 , i2 , i_tgfoid ) ;
char * tgfunc = NULL ;
1998-02-26 04:46:47 +00:00
int2 tgtype = atoi ( PQgetvalue ( res2 , i2 , i_tgtype ) ) ;
int tgnargs = atoi ( PQgetvalue ( res2 , i2 , i_tgnargs ) ) ;
1999-12-11 00:31:05 +00:00
const char * tgargs = PQgetvalue ( res2 , i2 , i_tgargs ) ;
2000-02-04 18:49:34 +00:00
int tgisconstraint ;
int tgdeferrable ;
int tginitdeferred ;
1999-12-11 00:31:05 +00:00
const char * p ;
1998-02-26 04:46:47 +00:00
int findx ;
2000-02-04 18:49:34 +00:00
if ( strcmp ( PQgetvalue ( res2 , i2 , i_tgisconstraint ) , " f " ) = = 0 )
tgisconstraint = 0 ;
else
tgisconstraint = 1 ;
if ( strcmp ( PQgetvalue ( res2 , i2 , i_tgdeferrable ) , " f " ) = = 0 )
tgdeferrable = 0 ;
else
tgdeferrable = 1 ;
if ( strcmp ( PQgetvalue ( res2 , i2 , i_tginitdeferred ) , " f " ) = = 0 )
tginitdeferred = 0 ;
else
tginitdeferred = 1 ;
1997-10-02 13:57:07 +00:00
for ( findx = 0 ; findx < numFuncs ; findx + + )
{
2000-02-04 18:49:34 +00:00
if ( strcmp ( finfo [ findx ] . oid , tgfuncoid ) = = 0 & &
1998-02-26 04:46:47 +00:00
finfo [ findx ] . nargs = = 0 & &
1997-10-02 13:57:07 +00:00
strcmp ( finfo [ findx ] . prorettype , " 0 " ) = = 0 )
break ;
}
2000-02-04 18:49:34 +00:00
1997-10-02 13:57:07 +00:00
if ( findx = = numFuncs )
{
2000-02-04 18:49:34 +00:00
PGresult * r ;
/*
* the funcname is an oid which we use to find the name of the
* pg_proc . We need to do this because getFuncs ( ) only reads
* in the user - defined funcs not all the funcs . We might not
* find what we want by looking in FuncInfo *
*/
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query ,
" SELECT proname from pg_proc "
" where pg_proc.oid = '%s'::oid " ,
tgfuncoid ) ;
r = PQexec ( g_conn , query - > data ) ;
if ( ! r | | PQresultStatus ( r ) ! = PGRES_TUPLES_OK )
{
fprintf ( stderr , " getTables(): SELECT (funcname) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
exit_nicely ( g_conn ) ;
}
tgfunc = strdup ( PQgetvalue ( r , 0 , PQfnumber ( r , " proname " ) ) ) ;
PQclear ( r ) ;
}
else {
tgfunc = strdup ( finfo [ findx ] . proname ) ;
1997-10-02 13:57:07 +00:00
}
1999-05-25 16:15:34 +00:00
#if 0
1999-01-21 22:53:37 +00:00
/* XXX - how to emit this DROP TRIGGER? */
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
2000-01-18 07:29:58 +00:00
appendPQExpBuffer ( query , " DROP TRIGGER %s " ,
fmtId ( PQgetvalue ( res2 , i2 , i_tgname ) ,
force_quotes ) ) ;
appendPQExpBuffer ( query , " ON %s; \n " ,
fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
1999-12-27 15:42:44 +00:00
fputs ( query - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
# endif
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
2000-02-04 18:49:34 +00:00
if ( tgisconstraint )
{
appendPQExpBuffer ( query , " CREATE CONSTRAINT TRIGGER " ) ;
appendPQExpBuffer ( query , fmtId ( PQgetvalue ( res2 , i2 , i_tgconstrname ) , force_quotes ) ) ;
}
else {
appendPQExpBuffer ( query , " CREATE TRIGGER " ) ;
appendPQExpBuffer ( query , fmtId ( PQgetvalue ( res2 , i2 , i_tgname ) , force_quotes ) ) ;
}
1999-12-27 18:21:07 +00:00
appendPQExpBufferChar ( query , ' ' ) ;
1997-10-02 13:57:07 +00:00
/* Trigger type */
findx = 0 ;
if ( TRIGGER_FOR_BEFORE ( tgtype ) )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " BEFORE " ) ;
1997-10-02 13:57:07 +00:00
else
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " AFTER " ) ;
1997-10-02 13:57:07 +00:00
if ( TRIGGER_FOR_INSERT ( tgtype ) )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " INSERT " ) ;
1997-10-02 13:57:07 +00:00
findx + + ;
}
if ( TRIGGER_FOR_DELETE ( tgtype ) )
{
if ( findx > 0 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " OR DELETE " ) ;
1997-10-02 13:57:07 +00:00
else
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " DELETE " ) ;
1997-10-02 13:57:07 +00:00
findx + + ;
}
if ( TRIGGER_FOR_UPDATE ( tgtype ) )
There's a patch attached to fix gcc 2.8.x warnings, except for the
yyerror ones from bison. It also includes a few 'enhancements' to
the C programming style (which are, of course, personal).
The other patch removes the compilation of backend/lib/qsort.c, as
qsort() is a standard function in stdlib.h and can be used any
where else (and it is). It was only used in
backend/optimizer/geqo/geqo_pool.c, backend/optimizer/path/predmig.c,
and backend/storage/page/bufpage.c
> > Some or all of these changes might not be appropriate for v6.3,
since we > > are in beta testing and since they do not affect the
current functionality. > > For those cases, how about submitting
patches based on the final v6.3 > > release?
There's more to come. Please review these patches. I ran the
regression tests and they only failed where this was expected
(random, geo, etc).
Cheers,
Jeroen
1998-03-30 16:47:35 +00:00
{
1997-10-02 13:57:07 +00:00
if ( findx > 0 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " OR UPDATE " ) ;
1997-10-02 13:57:07 +00:00
else
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " UPDATE " ) ;
There's a patch attached to fix gcc 2.8.x warnings, except for the
yyerror ones from bison. It also includes a few 'enhancements' to
the C programming style (which are, of course, personal).
The other patch removes the compilation of backend/lib/qsort.c, as
qsort() is a standard function in stdlib.h and can be used any
where else (and it is). It was only used in
backend/optimizer/geqo/geqo_pool.c, backend/optimizer/path/predmig.c,
and backend/storage/page/bufpage.c
> > Some or all of these changes might not be appropriate for v6.3,
since we > > are in beta testing and since they do not affect the
current functionality. > > For those cases, how about submitting
patches based on the final v6.3 > > release?
There's more to come. Please review these patches. I ran the
regression tests and they only failed where this was expected
(random, geo, etc).
Cheers,
Jeroen
1998-03-30 16:47:35 +00:00
}
2000-02-04 18:49:34 +00:00
appendPQExpBuffer ( query , " ON %s " , fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
if ( tgisconstraint )
{
if ( ! tgdeferrable )
{
appendPQExpBuffer ( query , " NOT " ) ;
}
appendPQExpBuffer ( query , " DEFERRABLE INITIALLY " ) ;
if ( tginitdeferred )
{
appendPQExpBuffer ( query , " DEFERRED " ) ;
}
else
{
appendPQExpBuffer ( query , " IMMEDIATE " ) ;
}
}
appendPQExpBuffer ( query , " FOR EACH ROW " ) ;
2000-01-18 07:29:58 +00:00
appendPQExpBuffer ( query , " EXECUTE PROCEDURE %s ( " ,
fmtId ( tgfunc , force_quotes ) ) ;
1997-10-02 13:57:07 +00:00
for ( findx = 0 ; findx < tgnargs ; findx + + )
{
1999-12-11 00:31:05 +00:00
const char * s ;
1998-02-26 04:46:47 +00:00
for ( p = tgargs ; ; )
1997-10-02 13:57:07 +00:00
{
1998-02-26 04:46:47 +00:00
p = strchr ( p , ' \\ ' ) ;
1997-10-02 13:57:07 +00:00
if ( p = = NULL )
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " getTables(): relation '%s': bad argument string (%s) for trigger '%s' \n " ,
1998-02-26 04:46:47 +00:00
tblinfo [ i ] . relname ,
PQgetvalue ( res2 , i2 , i_tgargs ) ,
PQgetvalue ( res2 , i2 , i_tgname ) ) ;
1997-10-02 13:57:07 +00:00
exit_nicely ( g_conn ) ;
}
p + + ;
if ( * p = = ' \\ ' )
{
p + + ;
continue ;
}
1998-02-26 04:46:47 +00:00
if ( p [ 0 ] = = ' 0 ' & & p [ 1 ] = = ' 0 ' & & p [ 2 ] = = ' 0 ' )
1997-10-02 13:57:07 +00:00
break ;
}
p - - ;
2000-01-18 07:29:58 +00:00
appendPQExpBufferChar ( query , ' \' ' ) ;
1999-12-27 15:45:04 +00:00
for ( s = tgargs ; s < p ; )
1997-10-02 13:57:07 +00:00
{
if ( * s = = ' \' ' )
2000-01-18 07:29:58 +00:00
appendPQExpBufferChar ( query , ' \\ ' ) ;
appendPQExpBufferChar ( query , * s + + ) ;
1997-10-02 13:57:07 +00:00
}
1999-12-27 18:21:07 +00:00
appendPQExpBufferChar ( query , ' \' ' ) ;
appendPQExpBuffer ( query , ( findx < tgnargs - 1 ) ? " , " : " " ) ;
1997-10-02 13:57:07 +00:00
tgargs = p + 4 ;
}
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " ); \n " ) ;
2000-02-04 18:49:34 +00:00
1999-12-27 15:42:44 +00:00
tblinfo [ i ] . triggers [ i2 ] = strdup ( query - > data ) ;
2000-01-18 18:09:02 +00:00
/*** Initialize trcomments and troids ***/
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " TRIGGER %s " ,
fmtId ( PQgetvalue ( res2 , i2 , i_tgname ) , force_quotes ) ) ;
appendPQExpBuffer ( query , " ON %s " ,
fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
tblinfo [ i ] . trcomments [ i2 ] = strdup ( query - > data ) ;
tblinfo [ i ] . troids [ i2 ] = strdup ( PQgetvalue ( res2 , i2 , i_tgoid ) ) ;
2000-02-04 18:49:34 +00:00
if ( tgfunc )
{
free ( tgfunc ) ;
}
1997-10-02 13:57:07 +00:00
}
PQclear ( res2 ) ;
}
else
2000-01-18 18:09:02 +00:00
{
1997-10-02 13:57:07 +00:00
tblinfo [ i ] . triggers = NULL ;
2000-01-18 18:09:02 +00:00
tblinfo [ i ] . trcomments = NULL ;
tblinfo [ i ] . troids = NULL ;
}
1997-09-07 05:04:48 +00:00
}
PQclear ( res ) ;
return tblinfo ;
1996-07-09 06:22:35 +00:00
}
/*
* getInherits
1997-09-07 05:04:48 +00:00
* read all the inheritance information
1996-07-09 06:22:35 +00:00
* from the system catalogs return them in the InhInfo * structure
*
1997-09-07 05:04:48 +00:00
* numInherits is set to the number of tables read in
*
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
InhInfo *
1996-07-09 06:22:35 +00:00
getInherits ( int * numInherits )
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
InhInfo * inhinfo ;
1997-09-07 05:04:48 +00:00
1999-11-22 17:56:41 +00:00
int i_inhrelid ;
1997-09-08 02:41:22 +00:00
int i_inhparent ;
1997-09-07 05:04:48 +00:00
/* find all the inheritance information */
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " SELECT inhrelid, inhparent from pg_inherits " ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getInherits(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
* numInherits = ntups ;
inhinfo = ( InhInfo * ) malloc ( ntups * sizeof ( InhInfo ) ) ;
1999-11-22 17:56:41 +00:00
i_inhrelid = PQfnumber ( res , " inhrelid " ) ;
1997-09-07 05:04:48 +00:00
i_inhparent = PQfnumber ( res , " inhparent " ) ;
for ( i = 0 ; i < ntups ; i + + )
{
1999-11-22 17:56:41 +00:00
inhinfo [ i ] . inhrelid = strdup ( PQgetvalue ( res , i , i_inhrelid ) ) ;
1997-09-07 05:04:48 +00:00
inhinfo [ i ] . inhparent = strdup ( PQgetvalue ( res , i , i_inhparent ) ) ;
}
PQclear ( res ) ;
return inhinfo ;
1996-07-09 06:22:35 +00:00
}
/*
* getTableAttrs -
1997-09-07 05:04:48 +00:00
* for each table in tblinfo , read its attributes types and names
*
1996-07-09 06:22:35 +00:00
* this is implemented in a very inefficient way right now , looping
1997-09-07 05:04:48 +00:00
* through the tblinfo and doing a join per table to find the attrs and their
1996-07-09 06:22:35 +00:00
* types
*
1997-09-07 05:04:48 +00:00
* modifies tblinfo
1996-07-09 06:22:35 +00:00
*/
void
1997-09-08 21:56:23 +00:00
getTableAttrs ( TableInfo * tblinfo , int numTables )
1996-07-09 06:22:35 +00:00
{
1997-09-08 02:41:22 +00:00
int i ,
j ;
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ;
1997-09-08 02:41:22 +00:00
int i_attname ;
int i_typname ;
1998-01-16 23:21:07 +00:00
int i_atttypmod ;
1997-09-08 02:41:22 +00:00
int i_attnotnull ;
1997-10-02 13:57:07 +00:00
int i_atthasdef ;
2000-01-18 18:09:02 +00:00
int i_attoid ;
1999-12-27 15:42:44 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numTables ; i + + )
{
if ( tblinfo [ i ] . sequence )
continue ;
/* find all the user attributes and their types */
/* we must read the attribute names in attribute number order! */
/*
* because we will use the attnum to index into the attnames array
* later
*/
if ( g_verbose )
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " %s finding the attrs and types for table: '%s' %s \n " ,
1997-09-07 05:04:48 +00:00
g_comment_start ,
tblinfo [ i ] . relname ,
g_comment_end ) ;
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
2000-01-18 18:09:02 +00:00
appendPQExpBuffer ( q , " SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, "
1997-10-02 13:57:07 +00:00
" a.attnotnull, a.atthasdef "
1997-09-07 05:04:48 +00:00
" from pg_attribute a, pg_type t "
" where a.attrelid = '%s'::oid and a.atttypid = t.oid "
" and a.attnum > 0 order by attnum " ,
tblinfo [ i ] . oid ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , q - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTableAttrs(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
2000-01-18 18:09:02 +00:00
i_attoid = PQfnumber ( res , " attoid " ) ;
1997-09-07 05:04:48 +00:00
i_attname = PQfnumber ( res , " attname " ) ;
i_typname = PQfnumber ( res , " typname " ) ;
1998-01-16 23:21:07 +00:00
i_atttypmod = PQfnumber ( res , " atttypmod " ) ;
1997-09-07 05:04:48 +00:00
i_attnotnull = PQfnumber ( res , " attnotnull " ) ;
1997-10-02 13:57:07 +00:00
i_atthasdef = PQfnumber ( res , " atthasdef " ) ;
1997-09-07 05:04:48 +00:00
tblinfo [ i ] . numatts = ntups ;
2000-01-18 18:09:02 +00:00
tblinfo [ i ] . attoids = ( char * * ) malloc ( ntups * sizeof ( char * ) ) ;
1997-09-07 05:04:48 +00:00
tblinfo [ i ] . attnames = ( char * * ) malloc ( ntups * sizeof ( char * ) ) ;
tblinfo [ i ] . typnames = ( char * * ) malloc ( ntups * sizeof ( char * ) ) ;
1998-01-16 23:21:07 +00:00
tblinfo [ i ] . atttypmod = ( int * ) malloc ( ntups * sizeof ( int ) ) ;
1997-09-07 05:04:48 +00:00
tblinfo [ i ] . inhAttrs = ( int * ) malloc ( ntups * sizeof ( int ) ) ;
tblinfo [ i ] . notnull = ( bool * ) malloc ( ntups * sizeof ( bool ) ) ;
1997-10-02 13:57:07 +00:00
tblinfo [ i ] . adef_expr = ( char * * ) malloc ( ntups * sizeof ( char * ) ) ;
1997-09-07 05:04:48 +00:00
tblinfo [ i ] . parentRels = NULL ;
tblinfo [ i ] . numParents = 0 ;
for ( j = 0 ; j < ntups ; j + + )
{
2000-01-18 18:09:02 +00:00
tblinfo [ i ] . attoids [ j ] = strdup ( PQgetvalue ( res , j , i_attoid ) ) ;
1997-09-07 05:04:48 +00:00
tblinfo [ i ] . attnames [ j ] = strdup ( PQgetvalue ( res , j , i_attname ) ) ;
tblinfo [ i ] . typnames [ j ] = strdup ( PQgetvalue ( res , j , i_typname ) ) ;
1998-01-16 23:21:07 +00:00
tblinfo [ i ] . atttypmod [ j ] = atoi ( PQgetvalue ( res , j , i_atttypmod ) ) ;
1997-09-07 05:04:48 +00:00
tblinfo [ i ] . inhAttrs [ j ] = 0 ; /* this flag is set in
* flagInhAttrs ( ) */
tblinfo [ i ] . notnull [ j ] = ( PQgetvalue ( res , j , i_attnotnull ) [ 0 ] = = ' t ' ) ? true : false ;
1997-10-02 13:57:07 +00:00
if ( PQgetvalue ( res , j , i_atthasdef ) [ 0 ] = = ' t ' )
{
PGresult * res2 ;
1998-02-26 04:46:47 +00:00
1997-10-02 13:57:07 +00:00
if ( g_verbose )
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " %s finding DEFAULT expression for attr: '%s' %s \n " ,
1997-10-02 13:57:07 +00:00
g_comment_start ,
tblinfo [ i ] . attnames [ j ] ,
g_comment_end ) ;
1998-02-26 04:46:47 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " SELECT adsrc from pg_attrdef "
1997-10-02 13:57:07 +00:00
" where adrelid = '%s'::oid and adnum = %d " ,
tblinfo [ i ] . oid , j + 1 ) ;
1999-12-27 15:42:44 +00:00
res2 = PQexec ( g_conn , q - > data ) ;
1997-10-02 13:57:07 +00:00
if ( ! res2 | |
1998-02-26 04:46:47 +00:00
PQresultStatus ( res2 ) ! = PGRES_TUPLES_OK )
1997-10-02 13:57:07 +00:00
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getTableAttrs(): SELECT (for DEFAULT) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-10-02 13:57:07 +00:00
exit_nicely ( g_conn ) ;
}
tblinfo [ i ] . adef_expr [ j ] = strdup ( PQgetvalue ( res2 , 0 , PQfnumber ( res2 , " adsrc " ) ) ) ;
PQclear ( res2 ) ;
}
else
tblinfo [ i ] . adef_expr [ j ] = NULL ;
1997-09-07 05:04:48 +00:00
}
PQclear ( res ) ;
}
1996-07-09 06:22:35 +00:00
}
/*
* getIndices
1997-09-07 05:04:48 +00:00
* read all the user - defined indices information
1996-07-09 06:22:35 +00:00
* from the system catalogs return them in the InhInfo * structure
*
1997-09-07 05:04:48 +00:00
* numIndices is set to the number of indices read in
*
1996-07-09 06:22:35 +00:00
*
*/
1997-09-08 02:41:22 +00:00
IndInfo *
1996-07-09 06:22:35 +00:00
getIndices ( int * numIndices )
{
1997-09-08 02:41:22 +00:00
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
1999-05-25 16:15:34 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
1999-05-25 16:15:34 +00:00
IndInfo * indinfo ;
1997-09-08 02:41:22 +00:00
int i_indexrelname ;
int i_indrelname ;
int i_indamname ;
int i_indproc ;
int i_indkey ;
int i_indclass ;
int i_indisunique ;
2000-01-18 18:09:02 +00:00
int i_indoid ;
1997-09-07 05:04:48 +00:00
/*
* find all the user - defined indices . We do not handle partial
* indices .
*
1999-06-03 04:01:16 +00:00
* Notice we skip indices on inversion objects ( relkind ' l ' )
1997-09-07 05:04:48 +00:00
*
* this is a 4 - way join ! !
*/
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query ,
2000-01-18 18:09:02 +00:00
" SELECT t1.oid as indoid, t1.relname as indexrelname, t2.relname as indrelname, "
1997-09-07 05:04:48 +00:00
" i.indproc, i.indkey, i.indclass, "
" a.amname as indamname, i.indisunique "
" from pg_index i, pg_class t1, pg_class t2, pg_am a "
1999-12-11 00:31:05 +00:00
" WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid "
1999-05-10 00:46:32 +00:00
" and t1.relam = a.oid and i.indexrelid > '%u'::oid "
1999-12-11 00:31:05 +00:00
" and t2.relname !~ '^pg_' and t2.relkind != 'l' and not i.indisprimary " ,
1997-09-07 05:04:48 +00:00
g_last_builtin_oid ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " getIndices(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
* numIndices = ntups ;
indinfo = ( IndInfo * ) malloc ( ntups * sizeof ( IndInfo ) ) ;
2000-01-16 03:54:58 +00:00
memset ( ( char * ) indinfo , 0 , ntups * sizeof ( IndInfo ) ) ;
2000-01-18 18:09:02 +00:00
i_indoid = PQfnumber ( res , " indoid " ) ;
1997-09-07 05:04:48 +00:00
i_indexrelname = PQfnumber ( res , " indexrelname " ) ;
i_indrelname = PQfnumber ( res , " indrelname " ) ;
i_indamname = PQfnumber ( res , " indamname " ) ;
i_indproc = PQfnumber ( res , " indproc " ) ;
i_indkey = PQfnumber ( res , " indkey " ) ;
i_indclass = PQfnumber ( res , " indclass " ) ;
i_indisunique = PQfnumber ( res , " indisunique " ) ;
for ( i = 0 ; i < ntups ; i + + )
{
2000-01-18 18:09:02 +00:00
indinfo [ i ] . indoid = strdup ( PQgetvalue ( res , i , i_indoid ) ) ;
1997-09-07 05:04:48 +00:00
indinfo [ i ] . indexrelname = strdup ( PQgetvalue ( res , i , i_indexrelname ) ) ;
indinfo [ i ] . indrelname = strdup ( PQgetvalue ( res , i , i_indrelname ) ) ;
indinfo [ i ] . indamname = strdup ( PQgetvalue ( res , i , i_indamname ) ) ;
indinfo [ i ] . indproc = strdup ( PQgetvalue ( res , i , i_indproc ) ) ;
2000-01-16 03:54:58 +00:00
parseNumericArray ( PQgetvalue ( res , i , i_indkey ) ,
indinfo [ i ] . indkey ,
INDEX_MAX_KEYS ) ;
parseNumericArray ( PQgetvalue ( res , i , i_indclass ) ,
indinfo [ i ] . indclass ,
INDEX_MAX_KEYS ) ;
1997-09-07 05:04:48 +00:00
indinfo [ i ] . indisunique = strdup ( PQgetvalue ( res , i , i_indisunique ) ) ;
}
PQclear ( res ) ;
return indinfo ;
1996-07-09 06:22:35 +00:00
}
2000-01-18 18:09:02 +00:00
/*------------------------------------------------------------------
* dumpComments - -
*
* This routine is used to dump any comments associated with the
* oid handed to this routine . The routine takes a constant character
* string for the target part of the object and the oid of the object
* whose comments are to be dumped . It is perfectly acceptable
* to hand an oid to this routine which has not been commented . In
* addition , the routine takes the stdio FILE handle to which the
* output should be written .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void dumpComment ( FILE * fout , const char * target , const char * oid ) {
PGresult * res ;
PQExpBuffer query ;
int i_description ;
/*** Build query to find comment ***/
query = createPQExpBuffer ( ) ;
appendPQExpBuffer ( query , " SELECT description FROM pg_description WHERE objoid = " ) ;
appendPQExpBuffer ( query , oid ) ;
/*** Execute query ***/
res = PQexec ( g_conn , query - > data ) ;
if ( ! res | | PQresultStatus ( res ) ! = PGRES_TUPLES_OK ) {
fprintf ( stderr , " DumpComment: SELECT failed: '%s'. \n " ,
PQerrorMessage ( g_conn ) ) ;
exit_nicely ( g_conn ) ;
}
/*** If a comment exists, build COMMENT ON statement ***/
if ( PQntuples ( res ) ! = 0 ) {
i_description = PQfnumber ( res , " description " ) ;
fprintf ( fout , " COMMENT ON %s IS '%s'; \n " ,
target , checkForQuote ( PQgetvalue ( res , 0 , i_description ) ) ) ;
}
/*** Clear the statement buffer and return ***/
PQclear ( res ) ;
}
/*------------------------------------------------------------------
* dumpDBComment - -
*
* This routine is used to dump any comments associated with the
* database to which we are currently connected . If the user chose
* to dump the schema of the database , then this is the first
* statement issued .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
void dumpDBComment ( FILE * fout ) {
PGresult * res ;
PQExpBuffer query ;
int i_oid ;
/*** Build query to find comment ***/
query = createPQExpBuffer ( ) ;
appendPQExpBuffer ( query , " SELECT oid FROM pg_database WHERE datname = '%s' " ,
PQdb ( g_conn ) ) ;
/*** Execute query ***/
res = PQexec ( g_conn , query - > data ) ;
if ( ! res | | PQresultStatus ( res ) ! = PGRES_TUPLES_OK ) {
fprintf ( stderr , " dumpDBComment: SELECT failed: '%s'. \n " ,
PQerrorMessage ( g_conn ) ) ;
exit_nicely ( g_conn ) ;
}
/*** If a comment exists, build COMMENT ON statement ***/
if ( PQntuples ( res ) ! = 0 ) {
i_oid = PQfnumber ( res , " oid " ) ;
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " DATABASE %s " , fmtId ( PQdb ( g_conn ) , force_quotes ) ) ;
dumpComment ( fout , query - > data , PQgetvalue ( res , 0 , i_oid ) ) ;
}
/*** Clear the statement buffer and return ***/
PQclear ( res ) ;
}
1996-07-09 06:22:35 +00:00
/*
* dumpTypes
1997-09-07 05:04:48 +00:00
* writes out to fout the queries to recreate all the user - defined types
1996-07-09 06:22:35 +00:00
*
*/
void
1997-09-08 21:56:23 +00:00
dumpTypes ( FILE * fout , FuncInfo * finfo , int numFuncs ,
TypeInfo * tinfo , int numTypes )
1996-07-09 06:22:35 +00:00
{
1997-09-08 02:41:22 +00:00
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ;
1997-09-08 02:41:22 +00:00
int funcInd ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numTypes ; i + + )
{
/* skip all the builtin types */
if ( atoi ( tinfo [ i ] . oid ) < g_last_builtin_oid )
continue ;
/* skip relation types */
if ( atoi ( tinfo [ i ] . typrelid ) ! = 0 )
continue ;
/* skip all array types that start w/ underscore */
if ( ( tinfo [ i ] . typname [ 0 ] = = ' _ ' ) & &
( strcmp ( tinfo [ i ] . typinput , " array_in " ) = = 0 ) )
continue ;
/*
* before we create a type , we need to create the input and output
* functions for it , if they haven ' t been created already
*/
funcInd = findFuncByName ( finfo , numFuncs , tinfo [ i ] . typinput ) ;
if ( funcInd ! = - 1 )
dumpOneFunc ( fout , finfo , funcInd , tinfo , numTypes ) ;
funcInd = findFuncByName ( finfo , numFuncs , tinfo [ i ] . typoutput ) ;
if ( funcInd ! = - 1 )
dumpOneFunc ( fout , finfo , funcInd , tinfo , numTypes ) ;
1998-07-19 05:24:51 +00:00
becomeUser ( fout , tinfo [ i ] . usename ) ;
1997-09-07 05:04:48 +00:00
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " DROP TYPE %s; \n " , fmtId ( tinfo [ i ] . typname , force_quotes ) ) ;
fputs ( q - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q ,
1998-08-25 15:02:04 +00:00
" CREATE TYPE %s "
1997-09-07 05:04:48 +00:00
" ( internallength = %s, externallength = %s, input = %s, "
" output = %s, send = %s, receive = %s, default = '%s' " ,
1998-12-13 23:41:32 +00:00
fmtId ( tinfo [ i ] . typname , force_quotes ) ,
1997-09-07 05:04:48 +00:00
tinfo [ i ] . typlen ,
tinfo [ i ] . typprtlen ,
tinfo [ i ] . typinput ,
tinfo [ i ] . typoutput ,
tinfo [ i ] . typsend ,
tinfo [ i ] . typreceive ,
tinfo [ i ] . typdefault ) ;
if ( tinfo [ i ] . isArray )
{
1997-09-08 02:41:22 +00:00
char * elemType ;
1997-09-07 05:04:48 +00:00
elemType = findTypeByOid ( tinfo , numTypes , tinfo [ i ] . typelem ) ;
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " , element = %s, delimiter = '%s' " ,
elemType , tinfo [ i ] . typdelim ) ;
1997-09-07 05:04:48 +00:00
}
if ( tinfo [ i ] . passedbyvalue )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ,passedbyvalue); \n " ) ;
1997-09-07 05:04:48 +00:00
else
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ); \n " ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
fputs ( q - > data , fout ) ;
2000-01-18 18:09:02 +00:00
/*** Dump Type Comments ***/
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " TYPE %s " , fmtId ( tinfo [ i ] . typname , force_quotes ) ) ;
dumpComment ( fout , q - > data , tinfo [ i ] . oid ) ;
1997-09-07 05:04:48 +00:00
}
1996-07-09 06:22:35 +00:00
}
1998-10-06 22:14:21 +00:00
/*
* dumpProcLangs
1999-05-25 16:15:34 +00:00
* writes out to fout the queries to recreate user - defined procedural languages
1998-10-06 22:14:21 +00:00
*
*/
void
dumpProcLangs ( FILE * fout , FuncInfo * finfo , int numFuncs ,
1999-05-25 16:15:34 +00:00
TypeInfo * tinfo , int numTypes )
1998-10-06 22:14:21 +00:00
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
PQExpBuffer query = createPQExpBuffer ( ) ;
1998-10-06 22:14:21 +00:00
int ntups ;
int i_lanname ;
int i_lanpltrusted ;
int i_lanplcallfoid ;
int i_lancompiler ;
1999-12-27 15:42:44 +00:00
char * lanname ;
char * lancompiler ;
const char * lanplcallfoid ;
1998-10-06 22:14:21 +00:00
int i ,
fidx ;
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query , " SELECT * FROM pg_language "
1998-10-06 22:14:21 +00:00
" WHERE lanispl "
" ORDER BY oid " ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1998-10-06 22:14:21 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpProcLangs(): SELECT failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1998-10-06 22:14:21 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
1999-05-25 16:15:34 +00:00
i_lanname = PQfnumber ( res , " lanname " ) ;
i_lanpltrusted = PQfnumber ( res , " lanpltrusted " ) ;
i_lanplcallfoid = PQfnumber ( res , " lanplcallfoid " ) ;
i_lancompiler = PQfnumber ( res , " lancompiler " ) ;
1998-10-06 22:14:21 +00:00
1999-05-25 16:15:34 +00:00
for ( i = 0 ; i < ntups ; i + + )
{
1998-10-06 22:14:21 +00:00
lanplcallfoid = PQgetvalue ( res , i , i_lanplcallfoid ) ;
for ( fidx = 0 ; fidx < numFuncs ; fidx + + )
{
if ( ! strcmp ( finfo [ fidx ] . oid , lanplcallfoid ) )
break ;
}
if ( fidx > = numFuncs )
{
fprintf ( stderr , " dumpProcLangs(): handler procedure for language %s not found \n " , PQgetvalue ( res , i , i_lanname ) ) ;
exit_nicely ( g_conn ) ;
}
dumpOneFunc ( fout , finfo , fidx , tinfo , numTypes ) ;
lanname = checkForQuote ( PQgetvalue ( res , i , i_lanname ) ) ;
lancompiler = checkForQuote ( PQgetvalue ( res , i , i_lancompiler ) ) ;
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
fprintf ( fout , " DROP PROCEDURAL LANGUAGE '%s'; \n " , lanname ) ;
1999-01-21 22:53:37 +00:00
1998-10-06 22:14:21 +00:00
fprintf ( fout , " CREATE %sPROCEDURAL LANGUAGE '%s' "
1999-05-25 16:15:34 +00:00
" HANDLER %s LANCOMPILER '%s'; \n " ,
( PQgetvalue ( res , i , i_lanpltrusted ) [ 0 ] = = ' t ' ) ? " TRUSTED " : " " ,
lanname ,
fmtId ( finfo [ fidx ] . proname , force_quotes ) ,
lancompiler ) ;
1998-10-06 22:14:21 +00:00
free ( lanname ) ;
free ( lancompiler ) ;
}
PQclear ( res ) ;
}
1996-07-09 06:22:35 +00:00
/*
* dumpFuncs
1997-09-07 05:04:48 +00:00
* writes out to fout the queries to recreate all the user - defined functions
1996-07-09 06:22:35 +00:00
*
*/
void
1997-09-08 21:56:23 +00:00
dumpFuncs ( FILE * fout , FuncInfo * finfo , int numFuncs ,
TypeInfo * tinfo , int numTypes )
1996-07-09 06:22:35 +00:00
{
1997-09-08 02:41:22 +00:00
int i ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numFuncs ; i + + )
dumpOneFunc ( fout , finfo , i , tinfo , numTypes ) ;
1996-07-09 06:22:35 +00:00
}
/*
* dumpOneFunc :
1997-09-07 05:04:48 +00:00
* dump out only one function , the index of which is given in the third
* argument
1996-07-09 06:22:35 +00:00
*
*/
1997-08-19 21:40:56 +00:00
static void
1997-09-08 21:56:23 +00:00
dumpOneFunc ( FILE * fout , FuncInfo * finfo , int i ,
TypeInfo * tinfo , int numTypes )
1996-07-09 06:22:35 +00:00
{
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ;
2000-01-18 18:09:02 +00:00
PQExpBuffer fnlist = createPQExpBuffer ( ) ;
1999-05-25 16:15:34 +00:00
int j ;
1999-12-27 15:42:44 +00:00
char * func_def ;
1998-10-06 22:14:21 +00:00
char func_lang [ NAMEDATALEN + 1 ] ;
1997-09-07 05:04:48 +00:00
if ( finfo [ i ] . dumped )
return ;
else
finfo [ i ] . dumped = 1 ;
1998-07-19 05:24:51 +00:00
becomeUser ( fout , finfo [ i ] . usename ) ;
1997-09-07 05:04:48 +00:00
1998-10-06 22:14:21 +00:00
if ( finfo [ i ] . lang = = INTERNALlanguageId )
{
func_def = finfo [ i ] . prosrc ;
strcpy ( func_lang , " INTERNAL " ) ;
}
else if ( finfo [ i ] . lang = = ClanguageId )
{
func_def = finfo [ i ] . probin ;
strcpy ( func_lang , " C " ) ;
}
else if ( finfo [ i ] . lang = = SQLlanguageId )
{
func_def = finfo [ i ] . prosrc ;
strcpy ( func_lang , " SQL " ) ;
}
else
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
int nlangs ;
int i_lanname ;
1998-10-06 22:14:21 +00:00
char query [ 256 ] ;
sprintf ( query , " SELECT lanname FROM pg_language "
1999-05-10 00:46:32 +00:00
" WHERE oid = %u " ,
1998-10-06 22:14:21 +00:00
finfo [ i ] . lang ) ;
res = PQexec ( g_conn , query ) ;
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpOneFunc(): SELECT for procedural language failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1998-10-06 22:14:21 +00:00
exit_nicely ( g_conn ) ;
}
nlangs = PQntuples ( res ) ;
if ( nlangs ! = 1 )
{
fprintf ( stderr , " dumpOneFunc(): procedural language for function %s not found \n " , finfo [ i ] . proname ) ;
exit_nicely ( g_conn ) ;
}
i_lanname = PQfnumber ( res , " lanname " ) ;
func_def = finfo [ i ] . prosrc ;
strcpy ( func_lang , PQgetvalue ( res , 0 , i_lanname ) ) ;
PQclear ( res ) ;
}
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " DROP FUNCTION %s ( " , fmtId ( finfo [ i ] . proname , force_quotes ) ) ;
1999-05-25 16:15:34 +00:00
for ( j = 0 ; j < finfo [ i ] . nargs ; j + + )
{
char * typname ;
typname = findTypeByOid ( tinfo , numTypes , finfo [ i ] . argtypes [ j ] ) ;
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " %s%s " ,
1999-05-25 16:15:34 +00:00
( j > 0 ) ? " , " : " " ,
fmtId ( typname , false ) ) ;
}
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ); \n " ) ;
fputs ( q - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " CREATE FUNCTION %s ( " , fmtId ( finfo [ i ] . proname , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
for ( j = 0 ; j < finfo [ i ] . nargs ; j + + )
{
1997-09-08 02:41:22 +00:00
char * typname ;
1997-09-07 05:04:48 +00:00
typname = findTypeByOid ( tinfo , numTypes , finfo [ i ] . argtypes [ j ] ) ;
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " %s%s " ,
1997-09-07 05:04:48 +00:00
( j > 0 ) ? " , " : " " ,
1998-12-13 23:41:32 +00:00
fmtId ( typname , false ) ) ;
2000-01-18 18:09:02 +00:00
appendPQExpBuffer ( fnlist , " %s%s " ,
( j > 0 ) ? " , " : " " ,
fmtId ( typname , false ) ) ;
1997-09-07 05:04:48 +00:00
}
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ) RETURNS %s%s AS '%s' LANGUAGE '%s'; \n " ,
1997-09-07 05:04:48 +00:00
( finfo [ i ] . retset ) ? " SETOF " : " " ,
1999-12-27 15:42:44 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , finfo [ i ] . prorettype ) , false ) ,
1998-10-06 22:14:21 +00:00
func_def , func_lang ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
fputs ( q - > data , fout ) ;
1996-07-09 06:22:35 +00:00
2000-01-18 18:09:02 +00:00
/*** Dump Function Comments ***/
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " FUNCTION %s " ,
fmtId ( finfo [ i ] . proname , force_quotes ) ) ;
appendPQExpBuffer ( q , " ( %s ) " , fnlist - > data ) ;
dumpComment ( fout , q - > data , finfo [ i ] . oid ) ;
1996-07-09 06:22:35 +00:00
}
/*
* dumpOprs
1997-09-07 05:04:48 +00:00
* writes out to fout the queries to recreate all the user - defined operators
1996-07-09 06:22:35 +00:00
*
*/
1997-09-07 05:04:48 +00:00
void
1997-09-08 21:56:23 +00:00
dumpOprs ( FILE * fout , OprInfo * oprinfo , int numOperators ,
TypeInfo * tinfo , int numTypes )
1996-07-09 06:22:35 +00:00
{
1999-05-25 16:15:34 +00:00
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ;
PQExpBuffer leftarg = createPQExpBuffer ( ) ;
PQExpBuffer rightarg = createPQExpBuffer ( ) ;
PQExpBuffer commutator = createPQExpBuffer ( ) ;
PQExpBuffer negator = createPQExpBuffer ( ) ;
PQExpBuffer restrictor = createPQExpBuffer ( ) ;
PQExpBuffer join = createPQExpBuffer ( ) ;
PQExpBuffer sort1 = createPQExpBuffer ( ) ;
PQExpBuffer sort2 = createPQExpBuffer ( ) ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numOperators ; i + + )
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( leftarg ) ;
resetPQExpBuffer ( rightarg ) ;
resetPQExpBuffer ( commutator ) ;
resetPQExpBuffer ( negator ) ;
resetPQExpBuffer ( restrictor ) ;
resetPQExpBuffer ( join ) ;
resetPQExpBuffer ( sort1 ) ;
resetPQExpBuffer ( sort2 ) ;
1997-09-07 05:04:48 +00:00
/* skip all the builtin oids */
if ( atoi ( oprinfo [ i ] . oid ) < g_last_builtin_oid )
continue ;
/*
* some operator are invalid because they were the result of user
* defining operators before commutators exist
*/
if ( strcmp ( oprinfo [ i ] . oprcode , " - " ) = = 0 )
continue ;
/*
* right unary means there ' s a left arg and left unary means
* there ' s a right arg
*/
if ( strcmp ( oprinfo [ i ] . oprkind , " r " ) = = 0 | |
strcmp ( oprinfo [ i ] . oprkind , " b " ) = = 0 )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( leftarg , " , \n \t LEFTARG = %s " ,
1999-05-25 16:15:34 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , oprinfo [ i ] . oprleft ) , false ) ) ;
1997-09-07 05:04:48 +00:00
}
if ( strcmp ( oprinfo [ i ] . oprkind , " l " ) = = 0 | |
strcmp ( oprinfo [ i ] . oprkind , " b " ) = = 0 )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( rightarg , " , \n \t RIGHTARG = %s " ,
1999-05-25 16:15:34 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , oprinfo [ i ] . oprright ) , false ) ) ;
1997-09-07 05:04:48 +00:00
}
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( oprinfo [ i ] . oprcom , " 0 " ) = = 0 ) )
appendPQExpBuffer ( commutator , " , \n \t COMMUTATOR = %s " ,
1997-09-07 05:04:48 +00:00
findOprByOid ( oprinfo , numOperators , oprinfo [ i ] . oprcom ) ) ;
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( oprinfo [ i ] . oprnegate , " 0 " ) = = 0 ) )
appendPQExpBuffer ( negator , " , \n \t NEGATOR = %s " ,
1997-09-07 05:04:48 +00:00
findOprByOid ( oprinfo , numOperators , oprinfo [ i ] . oprnegate ) ) ;
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( oprinfo [ i ] . oprrest , " - " ) = = 0 ) )
appendPQExpBuffer ( restrictor , " , \n \t RESTRICT = %s " , oprinfo [ i ] . oprrest ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( oprinfo [ i ] . oprjoin , " - " ) = = 0 ) )
appendPQExpBuffer ( join , " , \n \t JOIN = %s " , oprinfo [ i ] . oprjoin ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( oprinfo [ i ] . oprlsortop , " 0 " ) = = 0 ) )
appendPQExpBuffer ( sort1 , " , \n \t SORT1 = %s " ,
1999-05-25 16:15:34 +00:00
findOprByOid ( oprinfo , numOperators , oprinfo [ i ] . oprlsortop ) ) ;
1999-04-14 23:47:19 +00:00
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( oprinfo [ i ] . oprrsortop , " 0 " ) = = 0 ) )
appendPQExpBuffer ( sort2 , " , \n \t SORT2 = %s " ,
1999-05-25 16:15:34 +00:00
findOprByOid ( oprinfo , numOperators , oprinfo [ i ] . oprrsortop ) ) ;
1997-09-07 05:04:48 +00:00
1998-07-19 05:24:51 +00:00
becomeUser ( fout , oprinfo [ i ] . usename ) ;
1997-09-07 05:04:48 +00:00
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
2000-01-18 07:29:58 +00:00
appendPQExpBuffer ( q , " DROP OPERATOR %s (%s " , oprinfo [ i ] . oprname ,
fmtId ( findTypeByOid ( tinfo , numTypes , oprinfo [ i ] . oprleft ) ,
false ) ) ;
appendPQExpBuffer ( q , " , %s); \n " ,
fmtId ( findTypeByOid ( tinfo , numTypes , oprinfo [ i ] . oprright ) ,
false ) ) ;
1999-12-27 15:42:44 +00:00
fputs ( q - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q ,
1997-09-07 05:04:48 +00:00
" CREATE OPERATOR %s "
1999-04-14 23:47:19 +00:00
" (PROCEDURE = %s %s%s%s%s%s%s%s%s%s); \n " ,
1997-09-07 05:04:48 +00:00
oprinfo [ i ] . oprname ,
oprinfo [ i ] . oprcode ,
1999-12-27 15:42:44 +00:00
leftarg - > data ,
rightarg - > data ,
commutator - > data ,
negator - > data ,
restrictor - > data ,
1999-05-25 16:15:34 +00:00
( strcmp ( oprinfo [ i ] . oprcanhash , " t " ) = = 0 ) ? " , \n \t HASHES " : " " ,
1999-12-27 15:42:44 +00:00
join - > data ,
sort1 - > data ,
sort2 - > data ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
fputs ( q - > data , fout ) ;
1997-09-07 05:04:48 +00:00
}
1996-07-09 06:22:35 +00:00
}
/*
* dumpAggs
1997-09-07 05:04:48 +00:00
* writes out to fout the queries to create all the user - defined aggregates
1996-07-09 06:22:35 +00:00
*
*/
void
1997-09-08 21:56:23 +00:00
dumpAggs ( FILE * fout , AggInfo * agginfo , int numAggs ,
TypeInfo * tinfo , int numTypes )
1996-07-09 06:22:35 +00:00
{
1999-05-25 16:15:34 +00:00
int i ;
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ;
PQExpBuffer sfunc1 = createPQExpBuffer ( ) ;
PQExpBuffer sfunc2 = createPQExpBuffer ( ) ;
PQExpBuffer basetype = createPQExpBuffer ( ) ;
PQExpBuffer finalfunc = createPQExpBuffer ( ) ;
1997-09-08 02:41:22 +00:00
char comma1 [ 2 ] ,
1999-05-25 16:15:34 +00:00
comma2 [ 2 ] ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numAggs ; i + + )
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( sfunc1 ) ;
resetPQExpBuffer ( sfunc2 ) ;
resetPQExpBuffer ( basetype ) ;
resetPQExpBuffer ( finalfunc ) ;
1997-09-07 05:04:48 +00:00
/* skip all the builtin oids */
if ( atoi ( agginfo [ i ] . oid ) < g_last_builtin_oid )
continue ;
1998-02-26 04:46:47 +00:00
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( basetype ,
1997-10-02 13:57:07 +00:00
" BASETYPE = %s, " ,
1999-05-25 16:15:34 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , agginfo [ i ] . aggbasetype ) , false ) ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( agginfo [ i ] . aggtransfn1 , " - " ) = = 0 ) )
1997-09-07 05:04:48 +00:00
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( sfunc1 ,
1997-10-02 13:57:07 +00:00
" SFUNC1 = %s, STYPE1 = %s " ,
1997-09-07 05:04:48 +00:00
agginfo [ i ] . aggtransfn1 ,
1998-12-13 23:41:32 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , agginfo [ i ] . aggtranstype1 ) , false ) ) ;
1997-09-07 05:04:48 +00:00
if ( agginfo [ i ] . agginitval1 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( sfunc1 , " , INITCOND1 = '%s' " ,
agginfo [ i ] . agginitval1 ) ;
1997-09-07 05:04:48 +00:00
}
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( agginfo [ i ] . aggtransfn2 , " - " ) = = 0 ) )
1997-09-07 05:04:48 +00:00
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( sfunc2 ,
1997-09-07 05:04:48 +00:00
" SFUNC2 = %s, STYPE2 = %s " ,
agginfo [ i ] . aggtransfn2 ,
1998-12-13 23:41:32 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , agginfo [ i ] . aggtranstype2 ) , false ) ) ;
1997-09-07 05:04:48 +00:00
if ( agginfo [ i ] . agginitval2 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( sfunc2 , " , INITCOND2 = '%s' " ,
agginfo [ i ] . agginitval2 ) ;
1997-09-07 05:04:48 +00:00
}
1999-12-27 15:42:44 +00:00
if ( ! ( strcmp ( agginfo [ i ] . aggfinalfn , " - " ) = = 0 ) )
appendPQExpBuffer ( finalfunc , " FINALFUNC = %s " , agginfo [ i ] . aggfinalfn ) ;
if ( sfunc1 - > data [ 0 ] ! = ' \0 ' & & sfunc2 - > data [ 0 ] ! = ' \0 ' )
1997-09-07 05:04:48 +00:00
{
comma1 [ 0 ] = ' , ' ;
comma1 [ 1 ] = ' \0 ' ;
}
else
comma1 [ 0 ] = ' \0 ' ;
1999-12-27 15:42:44 +00:00
if ( finalfunc - > data [ 0 ] ! = ' \0 ' & & ( sfunc1 - > data [ 0 ] ! = ' \0 ' | | sfunc2 - > data [ 0 ] ! = ' \0 ' ) )
1997-09-07 05:04:48 +00:00
{
comma2 [ 0 ] = ' , ' ;
comma2 [ 1 ] = ' \0 ' ;
}
else
comma2 [ 0 ] = ' \0 ' ;
1998-07-19 05:24:51 +00:00
becomeUser ( fout , agginfo [ i ] . usename ) ;
1997-09-07 05:04:48 +00:00
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " DROP AGGREGATE %s %s; \n " , agginfo [ i ] . aggname ,
1999-05-25 16:15:34 +00:00
fmtId ( findTypeByOid ( tinfo , numTypes , agginfo [ i ] . aggbasetype ) , false ) ) ;
1999-12-27 15:42:44 +00:00
fputs ( q - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " CREATE AGGREGATE %s ( %s %s%s %s%s %s ); \n " ,
1997-09-07 05:04:48 +00:00
agginfo [ i ] . aggname ,
1999-12-27 15:42:44 +00:00
basetype - > data ,
sfunc1 - > data ,
1997-09-07 05:04:48 +00:00
comma1 ,
1999-12-27 15:42:44 +00:00
sfunc2 - > data ,
1997-09-07 05:04:48 +00:00
comma2 ,
1999-12-27 15:42:44 +00:00
finalfunc - > data ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
fputs ( q - > data , fout ) ;
2000-01-18 18:09:02 +00:00
/*** Dump Aggregate Comments ***/
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " AGGREGATE %s %s " , agginfo [ i ] . aggname ,
fmtId ( findTypeByOid ( tinfo , numTypes , agginfo [ i ] . aggbasetype ) , false ) ) ;
dumpComment ( fout , q - > data , agginfo [ i ] . oid ) ;
1997-09-07 05:04:48 +00:00
}
1996-07-09 06:22:35 +00:00
}
1997-12-04 01:31:28 +00:00
/*
* These are some support functions to fix the acl problem of pg_dump
*
* Matthew C . Aycock 12 / 02 / 97
*/
1998-12-05 22:09:57 +00:00
/* Append a keyword to a keyword list, inserting comma if needed.
* Caller must make aclbuf big enough for all possible keywords .
1997-12-04 01:31:28 +00:00
*/
1998-12-05 22:09:57 +00:00
static void
1999-05-25 16:15:34 +00:00
AddAcl ( char * aclbuf , const char * keyword )
1997-12-04 01:31:28 +00:00
{
1998-12-05 22:09:57 +00:00
if ( * aclbuf )
strcat ( aclbuf , " , " ) ;
strcat ( aclbuf , keyword ) ;
1997-12-04 01:31:28 +00:00
}
1998-02-26 04:46:47 +00:00
1997-12-04 01:31:28 +00:00
/*
1998-12-05 22:09:57 +00:00
* This will take a string of ' arwR ' and return a malloced ,
1997-12-04 01:31:28 +00:00
* comma delimited string of SELECT , INSERT , UPDATE , DELETE , RULE
*/
1997-12-26 08:45:27 +00:00
static char *
1998-12-05 22:09:57 +00:00
GetPrivileges ( const char * s )
1997-12-04 01:31:28 +00:00
{
1998-12-05 22:09:57 +00:00
char aclbuf [ 100 ] ;
1997-12-04 01:31:28 +00:00
1998-12-05 22:09:57 +00:00
aclbuf [ 0 ] = ' \0 ' ;
1997-12-04 01:31:28 +00:00
1998-04-07 22:36:38 +00:00
if ( strchr ( s , ' a ' ) )
1998-12-05 22:09:57 +00:00
AddAcl ( aclbuf , " INSERT " ) ;
1997-12-04 01:31:28 +00:00
1998-04-07 22:36:38 +00:00
if ( strchr ( s , ' w ' ) )
1998-12-05 22:09:57 +00:00
AddAcl ( aclbuf , " UPDATE,DELETE " ) ;
1998-04-07 22:36:38 +00:00
if ( strchr ( s , ' r ' ) )
1998-12-05 22:09:57 +00:00
AddAcl ( aclbuf , " SELECT " ) ;
1997-12-04 01:31:28 +00:00
1998-02-26 04:46:47 +00:00
if ( strchr ( s , ' R ' ) )
1998-12-05 22:09:57 +00:00
AddAcl ( aclbuf , " RULE " ) ;
1997-12-04 01:31:28 +00:00
1998-12-05 22:09:57 +00:00
/* Special-case when they're all there */
if ( strcmp ( aclbuf , " INSERT,UPDATE,DELETE,SELECT,RULE " ) = = 0 )
return strdup ( " ALL " ) ;
1998-02-26 04:46:47 +00:00
1998-12-05 22:09:57 +00:00
return strdup ( aclbuf ) ;
1997-12-04 01:31:28 +00:00
}
1998-09-01 04:40:42 +00:00
1998-04-07 22:36:38 +00:00
/*
* dumpACL :
1998-09-01 04:40:42 +00:00
* Write out grant / revoke information
* Called for sequences and tables
1998-04-07 22:36:38 +00:00
*/
1998-10-26 01:05:07 +00:00
static void
1998-04-07 22:36:38 +00:00
dumpACL ( FILE * fout , TableInfo tbinfo )
{
1998-12-05 22:09:57 +00:00
const char * acls = tbinfo . relacl ;
char * aclbuf ,
1999-05-25 16:15:34 +00:00
* tok ,
* eqpos ,
* priv ;
1998-12-05 22:09:57 +00:00
if ( strlen ( acls ) = = 0 )
return ; /* table has default permissions */
1999-05-25 16:15:34 +00:00
/*
* Revoke Default permissions for PUBLIC . Is this actually necessary ,
* or is it just a waste of time ?
1998-12-05 22:09:57 +00:00
*/
fprintf ( fout ,
" REVOKE ALL on %s from PUBLIC; \n " ,
1998-12-13 23:41:32 +00:00
fmtId ( tbinfo . relname , force_quotes ) ) ;
1998-12-05 22:09:57 +00:00
/* Make a working copy of acls so we can use strtok */
aclbuf = strdup ( acls ) ;
1998-04-07 22:36:38 +00:00
1998-12-05 22:09:57 +00:00
/* Scan comma-separated ACL items */
for ( tok = strtok ( aclbuf , " , " ) ; tok ! = NULL ; tok = strtok ( NULL , " , " ) )
1998-11-06 15:54:47 +00:00
{
1999-05-25 16:15:34 +00:00
/*
* Token may start with ' { ' and / or ' " ' . Actually only the start
* of the string should have ' { ' , but we don ' t verify that .
1998-12-05 22:09:57 +00:00
*/
if ( * tok = = ' { ' )
tok + + ;
if ( * tok = = ' " ' )
tok + + ;
/* User name is string up to = in tok */
eqpos = strchr ( tok , ' = ' ) ;
1999-05-25 16:15:34 +00:00
if ( ! eqpos )
1998-04-07 22:36:38 +00:00
{
1998-07-08 14:33:19 +00:00
fprintf ( stderr , " Could not parse ACL list for '%s'...Exiting! \n " ,
1998-04-07 22:36:38 +00:00
tbinfo . relname ) ;
exit_nicely ( g_conn ) ;
}
1999-05-25 16:15:34 +00:00
/*
* Parse the privileges ( right - hand side ) . Skip if there are
* none .
*/
1998-12-05 22:09:57 +00:00
priv = GetPrivileges ( eqpos + 1 ) ;
if ( * priv )
1998-07-19 05:24:51 +00:00
{
1998-11-15 07:09:13 +00:00
fprintf ( fout ,
" GRANT %s on %s to " ,
1998-12-13 23:41:32 +00:00
priv , fmtId ( tbinfo . relname , force_quotes ) ) ;
1999-05-25 16:15:34 +00:00
/*
* Note : fmtId ( ) can only be called once per printf , so don ' t
1998-12-05 22:09:57 +00:00
* try to merge printing of username into the above printf .
*/
if ( eqpos = = tok )
{
/* Empty left-hand side means "PUBLIC" */
1998-11-15 07:09:13 +00:00
fprintf ( fout , " PUBLIC; \n " ) ;
1998-12-05 22:09:57 +00:00
}
1998-07-19 05:24:51 +00:00
else
1998-12-05 22:09:57 +00:00
{
* eqpos = ' \0 ' ; /* it's ok to clobber aclbuf */
1999-05-26 21:51:13 +00:00
if ( strncmp ( tok , " group " , strlen ( " group " ) ) = = 0 )
fprintf ( fout , " GROUP %s; \n " ,
fmtId ( tok + strlen ( " group " ) , force_quotes ) ) ;
else
fprintf ( fout , " %s; \n " , fmtId ( tok , force_quotes ) ) ;
1998-12-05 22:09:57 +00:00
}
1998-07-19 05:24:51 +00:00
}
1998-12-05 22:09:57 +00:00
free ( priv ) ;
1998-04-07 22:36:38 +00:00
}
1998-12-05 22:09:57 +00:00
free ( aclbuf ) ;
1998-04-07 22:36:38 +00:00
}
1998-02-26 04:46:47 +00:00
1996-07-09 06:22:35 +00:00
/*
* dumpTables :
1997-09-07 05:04:48 +00:00
* write out to fout all the user - define tables
1996-07-09 06:22:35 +00:00
*/
1996-07-12 05:39:39 +00:00
1997-09-07 05:04:48 +00:00
void
1997-09-08 21:56:23 +00:00
dumpTables ( FILE * fout , TableInfo * tblinfo , int numTables ,
InhInfo * inhinfo , int numInherits ,
TypeInfo * tinfo , int numTypes , const char * tablename ,
1999-05-27 16:29:05 +00:00
const bool aclsSkip )
1996-07-09 06:22:35 +00:00
{
1997-09-08 02:41:22 +00:00
int i ,
j ,
1998-04-07 22:36:38 +00:00
k ;
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ;
char * serialSeq = NULL ; /* implicit sequence name created
1999-05-25 16:15:34 +00:00
* by SERIAL datatype */
const char * serialSeqSuffix = " _id_seq " ; /* suffix for implicit
* SERIAL sequences */
char * * parentRels ; /* list of names of parent relations */
1997-09-08 02:41:22 +00:00
int numParents ;
1999-05-25 16:15:34 +00:00
int actual_atts ; /* number of attrs in this CREATE statment */
int32 tmp_typmod ;
1999-05-13 02:35:44 +00:00
int precision ;
int scale ;
1998-02-26 04:46:47 +00:00
1997-10-02 13:57:07 +00:00
/* First - dump SEQUENCEs */
1999-01-18 06:32:27 +00:00
if ( tablename )
1999-05-25 16:15:34 +00:00
{
serialSeq = malloc ( strlen ( tablename ) + strlen ( serialSeqSuffix ) + 1 ) ;
strcpy ( serialSeq , tablename ) ;
strcat ( serialSeq , serialSeqSuffix ) ;
}
1997-10-02 13:57:07 +00:00
for ( i = 0 ; i < numTables ; i + + )
{
if ( ! ( tblinfo [ i ] . sequence ) )
continue ;
1999-01-18 06:32:27 +00:00
if ( ! tablename | | ( ! strcmp ( tblinfo [ i ] . relname , tablename ) )
1999-05-25 16:15:34 +00:00
| | ( serialSeq & & ! strcmp ( tblinfo [ i ] . relname , serialSeq ) ) )
1997-10-02 13:57:07 +00:00
{
1998-07-19 05:24:51 +00:00
becomeUser ( fout , tblinfo [ i ] . usename ) ;
1997-10-02 13:57:07 +00:00
dumpSequence ( fout , tblinfo [ i ] ) ;
1999-05-27 16:29:05 +00:00
if ( ! aclsSkip )
1998-04-07 22:36:38 +00:00
dumpACL ( fout , tblinfo [ i ] ) ;
1997-10-02 13:57:07 +00:00
}
}
1999-01-18 06:32:27 +00:00
if ( tablename )
1999-05-25 16:15:34 +00:00
free ( serialSeq ) ;
1998-02-26 04:46:47 +00:00
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numTables ; i + + )
{
1998-02-26 04:46:47 +00:00
if ( tblinfo [ i ] . sequence ) /* already dumped */
1997-10-02 13:57:07 +00:00
continue ;
1997-09-07 05:04:48 +00:00
if ( ! tablename | | ( ! strcmp ( tblinfo [ i ] . relname , tablename ) ) )
{
1998-10-06 22:14:21 +00:00
/* Skip VIEW relations */
1999-05-25 16:15:34 +00:00
1998-10-06 22:14:21 +00:00
/*
1999-05-25 16:15:34 +00:00
* if ( isViewRule ( tblinfo [ i ] . relname ) ) continue ;
*/
1997-09-07 05:04:48 +00:00
1998-10-06 22:14:21 +00:00
parentRels = tblinfo [ i ] . parentRels ;
numParents = tblinfo [ i ] . numParents ;
1997-09-07 05:04:48 +00:00
1998-10-06 22:14:21 +00:00
becomeUser ( fout , tblinfo [ i ] . usename ) ;
1997-09-07 05:04:48 +00:00
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " DROP TABLE %s; \n " , fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
fputs ( q - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " CREATE TABLE %s ( \n \t " , fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
1998-10-06 22:14:21 +00:00
actual_atts = 0 ;
for ( j = 0 ; j < tblinfo [ i ] . numatts ; j + + )
{
if ( tblinfo [ i ] . inhAttrs [ j ] = = 0 )
1998-10-06 03:09:02 +00:00
{
1998-12-05 22:09:57 +00:00
if ( actual_atts > 0 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " , \n \t " ) ;
appendPQExpBuffer ( q , " %s " ,
1998-12-13 23:41:32 +00:00
fmtId ( tblinfo [ i ] . attnames [ j ] , force_quotes ) ) ;
1998-10-06 22:14:21 +00:00
/* Show lengths on bpchar and varchar */
if ( ! strcmp ( tblinfo [ i ] . typnames [ j ] , " bpchar " ) )
1997-09-07 05:04:48 +00:00
{
1999-05-25 16:15:34 +00:00
int len = ( tblinfo [ i ] . atttypmod [ j ] - VARHDRSZ ) ;
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " character " ) ;
1998-12-13 23:41:32 +00:00
if ( len > 1 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " (%d) " ,
1998-12-13 23:41:32 +00:00
tblinfo [ i ] . atttypmod [ j ] - VARHDRSZ ) ;
1997-09-07 05:04:48 +00:00
}
1998-10-06 22:14:21 +00:00
else if ( ! strcmp ( tblinfo [ i ] . typnames [ j ] , " varchar " ) )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " character varying " ) ;
1998-12-05 22:09:57 +00:00
if ( tblinfo [ i ] . atttypmod [ j ] ! = - 1 )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " (%d) " ,
1998-12-05 22:09:57 +00:00
tblinfo [ i ] . atttypmod [ j ] - VARHDRSZ ) ;
1998-10-12 02:05:42 +00:00
}
1998-10-06 22:14:21 +00:00
}
1999-05-13 02:35:44 +00:00
else if ( ! strcmp ( tblinfo [ i ] . typnames [ j ] , " numeric " ) )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " numeric " ) ;
1999-05-13 02:35:44 +00:00
if ( tblinfo [ i ] . atttypmod [ j ] ! = - 1 )
{
tmp_typmod = tblinfo [ i ] . atttypmod [ j ] - VARHDRSZ ;
precision = ( tmp_typmod > > 16 ) & 0xffff ;
1999-05-25 16:15:34 +00:00
scale = tmp_typmod & 0xffff ;
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " (%d,%d) " ,
1999-05-25 16:15:34 +00:00
precision , scale ) ;
1999-05-13 02:35:44 +00:00
}
}
1999-05-25 16:15:34 +00:00
/*
* char is an internal single - byte data type ; Let ' s
* make sure we force it through with quotes . - thomas
* 1998 - 12 - 13
1998-12-13 23:41:32 +00:00
*/
else if ( ! strcmp ( tblinfo [ i ] . typnames [ j ] , " char " ) )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " %s " ,
1998-12-13 23:41:32 +00:00
fmtId ( tblinfo [ i ] . typnames [ j ] , true ) ) ;
}
1998-10-06 22:14:21 +00:00
else
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " %s " ,
1998-12-13 23:41:32 +00:00
fmtId ( tblinfo [ i ] . typnames [ j ] , false ) ) ;
1998-10-06 22:14:21 +00:00
}
if ( tblinfo [ i ] . adef_expr [ j ] ! = NULL )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " DEFAULT %s " ,
1998-12-05 22:09:57 +00:00
tblinfo [ i ] . adef_expr [ j ] ) ;
1998-10-06 22:14:21 +00:00
if ( tblinfo [ i ] . notnull [ j ] )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " NOT NULL " ) ;
1998-12-05 22:09:57 +00:00
actual_atts + + ;
1997-09-07 05:04:48 +00:00
}
1998-10-06 22:14:21 +00:00
}
1998-10-06 03:09:02 +00:00
1998-10-06 22:14:21 +00:00
/* put the CONSTRAINTS inside the table def */
for ( k = 0 ; k < tblinfo [ i ] . ncheck ; k + + )
{
1998-12-05 22:09:57 +00:00
if ( actual_atts + k > 0 )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " , \n \t " ) ;
appendPQExpBuffer ( q , " %s " ,
1998-10-06 22:14:21 +00:00
tblinfo [ i ] . check_expr [ k ] ) ;
}
1997-09-07 05:04:48 +00:00
2000-01-10 17:14:46 +00:00
/* PRIMARY KEY */
if ( tblinfo [ i ] . primary_key ) {
if ( actual_atts + tblinfo [ i ] . ncheck > 0 )
appendPQExpBuffer ( q , " , \n \t " ) ;
appendPQExpBuffer ( q , " PRIMARY KEY (%s) " , tblinfo [ i ] . primary_key ) ;
}
1999-12-11 00:31:05 +00:00
2000-01-10 17:14:46 +00:00
appendPQExpBuffer ( q , " \n ) " ) ;
1998-10-06 22:14:21 +00:00
if ( numParents > 0 )
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " \n inherits ( " ) ;
1998-10-06 22:14:21 +00:00
for ( k = 0 ; k < numParents ; k + + )
1998-10-06 03:09:02 +00:00
{
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " %s%s " ,
1998-10-06 22:14:21 +00:00
( k > 0 ) ? " , " : " " ,
1998-12-13 23:41:32 +00:00
fmtId ( parentRels [ k ] , force_quotes ) ) ;
1998-10-06 03:09:02 +00:00
}
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ) " ) ;
1998-10-06 22:14:21 +00:00
}
1998-10-06 03:09:02 +00:00
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( q , " ; \n " ) ;
fputs ( q - > data , fout ) ;
1999-05-27 16:29:05 +00:00
if ( ! aclsSkip )
1998-04-07 22:36:38 +00:00
dumpACL ( fout , tblinfo [ i ] ) ;
1998-10-06 22:14:21 +00:00
2000-01-18 18:09:02 +00:00
/* Dump Field Comments */
for ( j = 0 ; j < tblinfo [ i ] . numatts ; j + + ) {
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " COLUMN %s " , fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
appendPQExpBuffer ( q , " . " ) ;
appendPQExpBuffer ( q , " %s " , fmtId ( tblinfo [ i ] . attnames [ j ] , force_quotes ) ) ;
dumpComment ( fout , q - > data , tblinfo [ i ] . attoids [ j ] ) ;
}
/* Dump Table Comments */
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " TABLE %s " , fmtId ( tblinfo [ i ] . relname , force_quotes ) ) ;
dumpComment ( fout , q - > data , tblinfo [ i ] . oid ) ;
1997-09-07 05:04:48 +00:00
}
}
1996-07-09 06:22:35 +00:00
}
/*
* dumpIndices :
1997-09-07 05:04:48 +00:00
* write out to fout all the user - define indices
1996-07-09 06:22:35 +00:00
*/
1997-09-07 05:04:48 +00:00
void
1997-09-08 21:56:23 +00:00
dumpIndices ( FILE * fout , IndInfo * indinfo , int numIndices ,
TableInfo * tblinfo , int numTables , const char * tablename )
1996-07-09 06:22:35 +00:00
{
1997-09-08 02:41:22 +00:00
int i ,
k ;
int tableInd ;
1999-12-27 15:42:44 +00:00
PQExpBuffer attlist = createPQExpBuffer ( ) ;
1999-05-25 16:15:34 +00:00
char * classname [ INDEX_MAX_KEYS ] ;
char * funcname ; /* the name of the function to comput the
* index key from */
1997-09-08 02:41:22 +00:00
int indkey ,
indclass ;
int nclass ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
PQExpBuffer q = createPQExpBuffer ( ) ,
id1 = createPQExpBuffer ( ) ,
id2 = createPQExpBuffer ( ) ;
1997-09-08 02:41:22 +00:00
PGresult * res ;
1997-09-07 05:04:48 +00:00
for ( i = 0 ; i < numIndices ; i + + )
{
tableInd = findTableByName ( tblinfo , numTables ,
1998-09-20 03:18:43 +00:00
indinfo [ i ] . indrelname ) ;
if ( tableInd < 0 )
{
fprintf ( stderr , " failed sanity check, table %s was not found \n " ,
indinfo [ i ] . indrelname ) ;
2000-01-18 00:03:37 +00:00
exit ( 1 ) ;
1998-09-20 03:18:43 +00:00
}
1997-09-07 05:04:48 +00:00
if ( strcmp ( indinfo [ i ] . indproc , " 0 " ) = = 0 )
funcname = NULL ;
else
{
/*
* the funcname is an oid which we use to find the name of the
* pg_proc . We need to do this because getFuncs ( ) only reads
* in the user - defined funcs not all the funcs . We might not
* find what we want by looking in FuncInfo *
*/
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q ,
1997-09-07 05:04:48 +00:00
" SELECT proname from pg_proc "
" where pg_proc.oid = '%s'::oid " ,
indinfo [ i ] . indproc ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , q - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | | PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpIndices(): SELECT (funcname) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
funcname = strdup ( PQgetvalue ( res , 0 ,
PQfnumber ( res , " proname " ) ) ) ;
PQclear ( res ) ;
}
/* convert opclass oid(s) into names */
for ( nclass = 0 ; nclass < INDEX_MAX_KEYS ; nclass + + )
{
indclass = atoi ( indinfo [ i ] . indclass [ nclass ] ) ;
if ( indclass = = 0 )
break ;
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q ,
1997-09-07 05:04:48 +00:00
" SELECT opcname from pg_opclass "
" where pg_opclass.oid = '%u'::oid " ,
indclass ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , q - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | | PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpIndices(): SELECT (classname) failed. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
classname [ nclass ] = strdup ( PQgetvalue ( res , 0 ,
PQfnumber ( res , " opcname " ) ) ) ;
PQclear ( res ) ;
}
if ( funcname & & nclass ! = 1 )
{
fprintf ( stderr , " dumpIndices(): Must be exactly one OpClass "
" for functional index %s \n " , indinfo [ i ] . indexrelname ) ;
exit_nicely ( g_conn ) ;
}
/* convert attribute numbers into attribute list */
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( attlist ) ;
for ( k = 0 ; k < INDEX_MAX_KEYS ; k + + )
1997-09-07 05:04:48 +00:00
{
1997-09-08 02:41:22 +00:00
char * attname ;
1997-09-07 05:04:48 +00:00
indkey = atoi ( indinfo [ i ] . indkey [ k ] ) ;
1998-09-23 04:22:14 +00:00
if ( indkey = = InvalidAttrNumber )
1997-09-07 05:04:48 +00:00
break ;
indkey - - ;
if ( indkey = = ObjectIdAttributeNumber - 1 )
attname = " oid " ;
else
attname = tblinfo [ tableInd ] . attnames [ indkey ] ;
if ( funcname )
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( attlist , " %s%s " ,
1999-05-25 16:15:34 +00:00
( k = = 0 ) ? " " : " , " , fmtId ( attname , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
else
{
if ( k > = nclass )
{
fprintf ( stderr , " dumpIndices(): OpClass not found for "
1998-07-08 14:33:19 +00:00
" attribute '%s' of index '%s' \n " ,
1997-09-07 05:04:48 +00:00
attname , indinfo [ i ] . indexrelname ) ;
exit_nicely ( g_conn ) ;
}
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( id1 ) ;
resetPQExpBuffer ( id2 ) ;
appendPQExpBuffer ( id1 , fmtId ( attname , force_quotes ) ) ;
appendPQExpBuffer ( id2 , fmtId ( classname [ k ] , force_quotes ) ) ;
appendPQExpBuffer ( attlist , " %s%s %s " ,
( k = = 0 ) ? " " : " , " , id1 - > data , id2 - > data ) ;
1997-09-07 05:04:48 +00:00
free ( classname [ k ] ) ;
}
}
if ( ! tablename | | ( ! strcmp ( indinfo [ i ] . indrelname , tablename ) ) )
{
1999-05-25 16:15:34 +00:00
/*
* We make the index belong to the owner of its table , which
* is not necessarily right but should answer 99 % of the time .
* Would have to add owner name to IndInfo to do it right .
1998-10-01 01:49:12 +00:00
*/
becomeUser ( fout , tblinfo [ tableInd ] . usename ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( id1 ) ;
resetPQExpBuffer ( id2 ) ;
appendPQExpBuffer ( id1 , fmtId ( indinfo [ i ] . indexrelname , force_quotes ) ) ;
appendPQExpBuffer ( id2 , fmtId ( indinfo [ i ] . indrelname , force_quotes ) ) ;
1999-01-21 22:53:37 +00:00
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " DROP INDEX %s; \n " , id1 - > data ) ;
fputs ( q - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1998-11-15 07:09:13 +00:00
fprintf ( fout , " CREATE %s INDEX %s on %s using %s ( " ,
1997-09-07 05:04:48 +00:00
( strcmp ( indinfo [ i ] . indisunique , " t " ) = = 0 ) ? " UNIQUE " : " " ,
1999-12-27 15:42:44 +00:00
id1 - > data ,
id2 - > data ,
1997-09-07 05:04:48 +00:00
indinfo [ i ] . indamname ) ;
if ( funcname )
{
1998-11-15 07:09:13 +00:00
/* need 2 printf's here cuz fmtId has static return area */
1998-12-13 23:41:32 +00:00
fprintf ( fout , " %s " , fmtId ( funcname , false ) ) ;
1999-12-27 15:42:44 +00:00
fprintf ( fout , " (%s) %s ); \n " , attlist - > data , fmtId ( classname [ 0 ] , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
free ( funcname ) ;
free ( classname [ 0 ] ) ;
}
else
1999-12-27 15:42:44 +00:00
fprintf ( fout , " %s ); \n " , attlist - > data ) ;
2000-01-18 18:09:02 +00:00
/* Dump Index Comments */
resetPQExpBuffer ( q ) ;
appendPQExpBuffer ( q , " INDEX %s " , id1 - > data ) ;
dumpComment ( fout , q - > data , indinfo [ i ] . indoid ) ;
1997-09-07 05:04:48 +00:00
}
}
1996-07-09 06:22:35 +00:00
}
1997-09-07 05:04:48 +00:00
1996-07-09 06:22:35 +00:00
/*
1999-05-25 16:15:34 +00:00
* dumpTuples
1997-09-07 05:04:48 +00:00
* prints out the tuples in ASCII representation . The output is a valid
* input to COPY FROM stdin .
*
* We only need to do this for POSTGRES 4.2 databases since the
* COPY TO statment doesn ' t escape newlines properly . It ' s been fixed
1998-03-14 21:58:09 +00:00
* in PostgreSQL .
1996-07-09 06:22:35 +00:00
*
* the attrmap passed in tells how to map the attributes copied in to the
* attributes copied out
*/
1997-08-19 21:40:56 +00:00
# ifdef NOT_USED
1996-07-09 06:22:35 +00:00
void
1997-09-08 21:56:23 +00:00
dumpTuples ( PGresult * res , FILE * fout , int * attrmap )
1996-07-09 06:22:35 +00:00
{
1997-09-08 02:41:22 +00:00
int j ,
k ;
int m ,
n ;
1999-05-25 16:15:34 +00:00
char * * outVals = NULL ; /* values to copy out */
1997-09-07 05:04:48 +00:00
n = PQntuples ( res ) ;
m = PQnfields ( res ) ;
if ( m > 0 )
{
/*
* Print out the tuples but only print tuples with at least 1
* field .
*/
outVals = ( char * * ) malloc ( m * sizeof ( char * ) ) ;
for ( j = 0 ; j < n ; j + + )
{
for ( k = 0 ; k < m ; k + + )
outVals [ attrmap [ k ] ] = PQgetvalue ( res , j , k ) ;
for ( k = 0 ; k < m ; k + + )
{
1997-09-08 02:41:22 +00:00
char * pval = outVals [ k ] ;
1997-09-07 05:04:48 +00:00
if ( k ! = 0 )
fputc ( ' \t ' , fout ) ; /* delimiter for attribute */
if ( pval )
{
while ( * pval ! = ' \0 ' )
{
/* escape tabs, newlines and backslashes */
if ( * pval = = ' \t ' | | * pval = = ' \n ' | | * pval = = ' \\ ' )
fputc ( ' \\ ' , fout ) ;
fputc ( * pval , fout ) ;
pval + + ;
}
}
}
fputc ( ' \n ' , fout ) ; /* delimiter for a tuple */
}
free ( outVals ) ;
}
1996-07-09 06:22:35 +00:00
}
1997-09-07 05:04:48 +00:00
1997-08-19 21:40:56 +00:00
# endif
1996-07-09 06:22:35 +00:00
1996-08-24 20:49:41 +00:00
/*
* setMaxOid -
* find the maximum oid and generate a COPY statement to set it
*/
1996-07-09 06:22:35 +00:00
1997-08-19 21:40:56 +00:00
static void
1997-09-08 21:56:23 +00:00
setMaxOid ( FILE * fout )
1996-08-24 20:49:41 +00:00
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
Oid max_oid ;
1997-09-07 05:04:48 +00:00
res = PQexec ( g_conn , " CREATE TABLE pgdump_oid (dummy int4) " ) ;
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " Can not create pgdump_oid table. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
PQclear ( res ) ;
res = PQexec ( g_conn , " INSERT INTO pgdump_oid VALUES (0) " ) ;
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " Can not insert into pgdump_oid table. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
max_oid = atol ( PQoidStatus ( res ) ) ;
if ( max_oid = = 0 )
{
fprintf ( stderr , " Invalid max id in setMaxOid \n " ) ;
exit_nicely ( g_conn ) ;
}
PQclear ( res ) ;
res = PQexec ( g_conn , " DROP TABLE pgdump_oid; " ) ;
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " Can not drop pgdump_oid table. Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
PQclear ( res ) ;
if ( g_verbose )
1999-05-10 00:46:32 +00:00
fprintf ( stderr , " %s maximum system oid is %u %s \n " ,
1997-09-07 05:04:48 +00:00
g_comment_start , max_oid , g_comment_end ) ;
fprintf ( fout , " CREATE TABLE pgdump_oid (dummy int4); \n " ) ;
fprintf ( fout , " COPY pgdump_oid WITH OIDS FROM stdin; \n " ) ;
fprintf ( fout , " %-d \t 0 \n " , max_oid ) ;
fprintf ( fout , " \\ . \n " ) ;
fprintf ( fout , " DROP TABLE pgdump_oid; \n " ) ;
}
1996-07-09 06:22:35 +00:00
/*
* findLastBuiltInOid -
1997-09-07 05:04:48 +00:00
* find the last built in oid
1996-07-09 06:22:35 +00:00
* we do this by looking up the oid of ' template1 ' in pg_database ,
1997-09-07 05:04:48 +00:00
* this is probably not foolproof but comes close
1996-07-09 06:22:35 +00:00
*/
1997-08-19 21:40:56 +00:00
static int
1996-10-07 03:30:40 +00:00
findLastBuiltinOid ( void )
1996-07-09 06:22:35 +00:00
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
1997-09-08 02:41:22 +00:00
int ntups ;
int last_oid ;
1997-09-07 05:04:48 +00:00
res = PQexec ( g_conn ,
" SELECT oid from pg_database where datname = 'template1' " ) ;
if ( res = = NULL | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-10-10 14:42:44 +00:00
fprintf ( stderr , " pg_dump error in finding the template1 database. " ) ;
fprintf ( stderr , " Explanation from backend: '%s'. \n " , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
ntups = PQntuples ( res ) ;
1999-10-10 17:00:26 +00:00
if ( ntups < 1 )
1997-09-07 05:04:48 +00:00
{
1999-10-10 14:42:44 +00:00
fprintf ( stderr , " pg_dump: couldn't find the template1 database. \n " ) ;
1999-10-10 17:00:26 +00:00
fprintf ( stderr , " There is no 'template1' entry in the 'pg_database' table. \n " ) ;
exit_nicely ( g_conn ) ;
}
if ( ntups > 1 )
{
fprintf ( stderr , " pg_dump: found more than one template1 database. \n " ) ;
fprintf ( stderr , " There is more than one 'template1' entry in the 'pg_database' table \n " ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
last_oid = atoi ( PQgetvalue ( res , 0 , PQfnumber ( res , " oid " ) ) ) ;
PQclear ( res ) ;
return last_oid ;
1996-07-09 06:22:35 +00:00
}
/*
* checkForQuote :
1997-09-07 05:04:48 +00:00
* checks a string for quote characters and quotes them
1996-07-09 06:22:35 +00:00
*/
1997-09-08 02:41:22 +00:00
static char *
1997-09-07 05:04:48 +00:00
checkForQuote ( const char * s )
1996-07-09 06:22:35 +00:00
{
1999-05-25 16:15:34 +00:00
char * r ;
1997-09-08 02:41:22 +00:00
char c ;
1999-05-25 16:15:34 +00:00
char * result ;
1996-07-09 06:22:35 +00:00
1997-09-08 02:41:22 +00:00
int j = 0 ;
1996-07-09 06:22:35 +00:00
1997-09-07 05:04:48 +00:00
r = malloc ( strlen ( s ) * 3 + 1 ) ; /* definitely long enough */
1996-07-09 06:22:35 +00:00
1997-09-07 05:04:48 +00:00
while ( ( c = * s ) ! = ' \0 ' )
{
1996-07-09 06:22:35 +00:00
1997-09-07 05:04:48 +00:00
if ( c = = ' \' ' )
{
r [ j + + ] = ' \' ' ; /* quote the single quotes */
}
r [ j + + ] = c ;
s + + ;
}
r [ j ] = ' \0 ' ;
result = strdup ( r ) ;
free ( r ) ;
1996-07-09 06:22:35 +00:00
1997-09-07 05:04:48 +00:00
return result ;
1996-07-09 06:22:35 +00:00
}
1997-04-02 04:17:27 +00:00
1997-09-07 05:04:48 +00:00
static void
1997-09-08 21:56:23 +00:00
dumpSequence ( FILE * fout , TableInfo tbinfo )
1997-04-02 04:17:27 +00:00
{
1999-12-27 15:42:44 +00:00
PGresult * res ;
1999-05-25 16:15:34 +00:00
int4 last ,
1997-09-08 02:41:22 +00:00
incby ,
maxv ,
minv ,
cache ;
1999-05-25 16:15:34 +00:00
char cycled ,
1999-12-11 00:31:05 +00:00
called ;
1999-12-27 15:42:44 +00:00
const char * t ;
PQExpBuffer query = createPQExpBuffer ( ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
appendPQExpBuffer ( query ,
1997-09-07 05:04:48 +00:00
" SELECT sequence_name, last_value, increment_by, max_value, "
1998-08-25 15:02:04 +00:00
" min_value, cache_value, is_cycled, is_called from %s " ,
1998-12-13 23:41:32 +00:00
fmtId ( tbinfo . relname , force_quotes ) ) ;
1997-09-07 05:04:48 +00:00
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1997-09-07 05:04:48 +00:00
if ( ! res | | PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpSequence(%s): SELECT failed. Explanation from backend: '%s'. \n " , tbinfo . relname , PQerrorMessage ( g_conn ) ) ;
1997-09-07 05:04:48 +00:00
exit_nicely ( g_conn ) ;
}
if ( PQntuples ( res ) ! = 1 )
{
fprintf ( stderr , " dumpSequence(%s): %d (!= 1) tuples returned by SELECT \n " ,
tbinfo . relname , PQntuples ( res ) ) ;
exit_nicely ( g_conn ) ;
}
if ( strcmp ( PQgetvalue ( res , 0 , 0 ) , tbinfo . relname ) ! = 0 )
{
fprintf ( stderr , " dumpSequence(%s): different sequence name "
" returned by SELECT: %s \n " ,
tbinfo . relname , PQgetvalue ( res , 0 , 0 ) ) ;
exit_nicely ( g_conn ) ;
}
last = atoi ( PQgetvalue ( res , 0 , 1 ) ) ;
incby = atoi ( PQgetvalue ( res , 0 , 2 ) ) ;
maxv = atoi ( PQgetvalue ( res , 0 , 3 ) ) ;
minv = atoi ( PQgetvalue ( res , 0 , 4 ) ) ;
cache = atoi ( PQgetvalue ( res , 0 , 5 ) ) ;
t = PQgetvalue ( res , 0 , 6 ) ;
cycled = * t ;
t = PQgetvalue ( res , 0 , 7 ) ;
called = * t ;
PQclear ( res ) ;
1999-05-26 16:06:45 +00:00
if ( dropSchema )
1999-05-25 16:15:34 +00:00
{
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " DROP SEQUENCE %s; \n " , fmtId ( tbinfo . relname , force_quotes ) ) ;
fputs ( query - > data , fout ) ;
1999-05-25 16:15:34 +00:00
}
1999-01-21 22:53:37 +00:00
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query ,
1998-08-25 15:02:04 +00:00
" CREATE SEQUENCE %s start %d increment %d maxvalue %d "
1997-09-07 05:04:48 +00:00
" minvalue %d cache %d %s; \n " ,
1999-05-25 16:15:34 +00:00
fmtId ( tbinfo . relname , force_quotes ) , last , incby , maxv , minv , cache ,
1997-09-07 05:04:48 +00:00
( cycled = = ' t ' ) ? " cycle " : " " ) ;
1999-12-27 15:42:44 +00:00
fputs ( query - > data , fout ) ;
1997-09-07 05:04:48 +00:00
2000-01-18 18:09:02 +00:00
/* Dump Sequence Comments */
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " SEQUENCE %s " , fmtId ( tbinfo . relname , force_quotes ) ) ;
dumpComment ( fout , query - > data , tbinfo . oid ) ;
1997-09-07 05:04:48 +00:00
if ( called = = ' f ' )
return ; /* nothing to do more */
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " SELECT nextval ('%s'); \n " , fmtId ( tbinfo . relname , force_quotes ) ) ;
fputs ( query - > data , fout ) ;
1997-04-02 04:17:27 +00:00
}
1997-10-02 13:57:07 +00:00
1998-02-26 04:46:47 +00:00
static void
dumpTriggers ( FILE * fout , const char * tablename ,
TableInfo * tblinfo , int numTables )
1997-10-02 13:57:07 +00:00
{
1998-02-26 04:46:47 +00:00
int i ,
j ;
1997-10-02 13:57:07 +00:00
if ( g_verbose )
fprintf ( stderr , " %s dumping out triggers %s \n " ,
g_comment_start , g_comment_end ) ;
1998-02-26 04:46:47 +00:00
1997-10-02 13:57:07 +00:00
for ( i = 0 ; i < numTables ; i + + )
{
if ( tablename & & strcmp ( tblinfo [ i ] . relname , tablename ) )
continue ;
for ( j = 0 ; j < tblinfo [ i ] . ntrig ; j + + )
{
1998-07-19 05:24:51 +00:00
becomeUser ( fout , tblinfo [ i ] . usename ) ;
1997-10-02 13:57:07 +00:00
fputs ( tblinfo [ i ] . triggers [ j ] , fout ) ;
2000-01-18 18:09:02 +00:00
dumpComment ( fout , tblinfo [ i ] . trcomments [ j ] , tblinfo [ i ] . troids [ j ] ) ;
1997-10-02 13:57:07 +00:00
}
}
}
1998-07-19 05:24:51 +00:00
1998-10-06 22:14:21 +00:00
static void
dumpRules ( FILE * fout , const char * tablename ,
1999-05-25 16:15:34 +00:00
TableInfo * tblinfo , int numTables )
1998-10-06 22:14:21 +00:00
{
1999-05-25 16:15:34 +00:00
PGresult * res ;
int nrules ;
int i ,
t ;
1999-12-27 15:42:44 +00:00
PQExpBuffer query = createPQExpBuffer ( ) ;
1998-10-06 22:14:21 +00:00
1999-05-25 16:15:34 +00:00
int i_definition ;
2000-01-18 18:09:02 +00:00
int i_oid ;
int i_rulename ;
1998-10-06 22:14:21 +00:00
if ( g_verbose )
fprintf ( stderr , " %s dumping out rules %s \n " ,
g_comment_start , g_comment_end ) ;
/*
* For each table we dump
*/
for ( t = 0 ; t < numTables ; t + + )
{
if ( tablename & & strcmp ( tblinfo [ t ] . relname , tablename ) )
continue ;
/*
* Get all rules defined for this table
*/
1999-12-27 15:42:44 +00:00
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " SELECT pg_get_ruledef(pg_rewrite.rulename) "
2000-01-18 18:09:02 +00:00
" AS definition, pg_rewrite.oid, pg_rewrite.rulename FROM pg_rewrite, pg_class "
1998-10-06 22:14:21 +00:00
" WHERE pg_class.relname = '%s' "
" AND pg_rewrite.ev_class = pg_class.oid "
" ORDER BY pg_rewrite.oid " ,
tblinfo [ t ] . relname ) ;
1999-12-27 15:42:44 +00:00
res = PQexec ( g_conn , query - > data ) ;
1998-10-06 22:14:21 +00:00
if ( ! res | |
PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
{
1999-05-15 22:18:51 +00:00
fprintf ( stderr , " dumpRules(): SELECT failed for table %s. Explanation from backend: '%s'. \n " ,
tblinfo [ t ] . relname , PQerrorMessage ( g_conn ) ) ;
1998-10-06 22:14:21 +00:00
exit_nicely ( g_conn ) ;
}
nrules = PQntuples ( res ) ;
i_definition = PQfnumber ( res , " definition " ) ;
2000-01-18 18:09:02 +00:00
i_oid = PQfnumber ( res , " oid " ) ;
i_rulename = PQfnumber ( res , " rulename " ) ;
1998-10-06 22:14:21 +00:00
/*
* Dump them out
*/
2000-01-18 18:09:02 +00:00
for ( i = 0 ; i < nrules ; i + + ) {
1998-10-06 22:14:21 +00:00
fprintf ( fout , " %s \n " , PQgetvalue ( res , i , i_definition ) ) ;
2000-01-18 18:09:02 +00:00
/* Dump rule comments */
resetPQExpBuffer ( query ) ;
appendPQExpBuffer ( query , " RULE %s " , fmtId ( PQgetvalue ( res , i , i_rulename ) , force_quotes ) ) ;
dumpComment ( fout , query - > data , PQgetvalue ( res , i , i_oid ) ) ;
}
1998-10-06 22:14:21 +00:00
PQclear ( res ) ;
}
}
1998-07-19 05:24:51 +00:00
/* Issue a psql \connect command to become the specified user.
* We want to do this only if we are dumping ACLs ,
* and only if the new username is different from the last one
* ( to avoid the overhead of useless backend launches ) .
*/
1998-09-01 04:40:42 +00:00
static void
becomeUser ( FILE * fout , const char * username )
1998-07-19 05:24:51 +00:00
{
static const char * lastusername = " " ;
1999-05-27 16:29:05 +00:00
if ( aclsSkip )
1998-07-19 05:24:51 +00:00
return ;
if ( strcmp ( lastusername , username ) = = 0 )
return ;
fprintf ( fout , " \\ connect - %s \n " , username ) ;
lastusername = username ;
}