@ -14,6 +14,7 @@
# include <ctype.h>
# include "catalog/pg_am.h"
# include "catalog/pg_attribute_d.h"
# include "catalog/pg_cast_d.h"
# include "catalog/pg_class_d.h"
@ -6015,3 +6016,337 @@ printACLColumn(PQExpBuffer buf, const char *colname)
" pg_catalog.array_to_string(%s, ' \\ n') AS \" %s \" " ,
colname , gettext_noop ( " Access privileges " ) ) ;
}
/*
* \ dAc
* Lists operator classes
*
* Takes an optional regexps to filter by index access method and type .
*/
bool
listOperatorClasses ( const char * access_method_pattern ,
const char * type_pattern , bool verbose )
{
PQExpBufferData buf ;
PGresult * res ;
printQueryOpt myopt = pset . popt ;
bool have_where = false ;
static const bool translate_columns [ ] = { false , false , false , false , false ,
false , false , false } ;
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
" SELECT DISTINCT "
" am.amname AS \" %s \" , \n "
" c.opcintype::pg_catalog.regtype AS \" %s \" , \n "
" (CASE WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype \n "
" THEN c.opckeytype \n "
" ELSE NULL -- c.opcintype \n "
" END)::pg_catalog.regtype AS \" %s \" , \n "
" CASE \n "
" WHEN pg_catalog.pg_opclass_is_visible(c.oid) \n "
" THEN format('%%I', c.opcname) \n "
" ELSE format('%%I.%%I', n.nspname, c.opcname) \n "
" END AS \" %s \" , \n "
" (CASE WHEN c.opcdefault \n "
" THEN '%s' \n "
" ELSE '%s' \n "
" END) AS \" %s \" " ,
gettext_noop ( " AM " ) ,
gettext_noop ( " Input type " ) ,
gettext_noop ( " Storage type " ) ,
gettext_noop ( " Operator class " ) ,
gettext_noop ( " yes " ) ,
gettext_noop ( " no " ) ,
gettext_noop ( " Default? " ) ) ;
if ( verbose )
appendPQExpBuffer ( & buf ,
" , \n CASE \n "
" WHEN pg_catalog.pg_opfamily_is_visible(of.oid) \n "
" THEN format('%%I', of.opfname) \n "
" ELSE format('%%I.%%I', ofn.nspname, of.opfname) \n "
" END AS \" %s \" , \n "
" pg_catalog.pg_get_userbyid(c.opcowner) AS \" %s \" \n " ,
gettext_noop ( " Operator family " ) ,
gettext_noop ( " Owner " ) ) ;
appendPQExpBuffer ( & buf ,
" \n FROM pg_catalog.pg_opclass c \n "
" LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod \n "
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace \n "
" LEFT JOIN pg_catalog.pg_type t1 ON t1.oid = c.opcintype \n "
) ;
if ( verbose )
appendPQExpBuffer ( & buf ,
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily \n "
" LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace \n " ) ;
if ( access_method_pattern )
have_where = processSQLNamePattern ( pset . db , & buf , access_method_pattern ,
false , false , NULL , " am.amname " , NULL , NULL ) ;
if ( type_pattern )
processSQLNamePattern ( pset . db , & buf , type_pattern , have_where , false ,
NULL , " t1.typname " , NULL , NULL ) ;
appendPQExpBufferStr ( & buf , " ORDER BY 1, 2, 4; " ) ;
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
myopt . title = _ ( " List of operator classes " ) ;
myopt . translate_header = true ;
myopt . translate_columns = translate_columns ;
myopt . n_translate_columns = lengthof ( translate_columns ) ;
printQuery ( res , & myopt , pset . queryFout , false , pset . logfile ) ;
PQclear ( res ) ;
return true ;
}
/*
* \ dAf
* Lists operator families
*
* Takes an optional regexps to filter by index access method and type .
*/
bool
listOperatorFamilies ( const char * access_method_pattern ,
const char * type_pattern , bool verbose )
{
PQExpBufferData buf ;
PGresult * res ;
printQueryOpt myopt = pset . popt ;
bool have_where = false ;
static const bool translate_columns [ ] = { false , false , false , false , false ,
false , false , false } ;
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
" SELECT DISTINCT "
" am.amname AS \" %s \" , \n "
" CASE \n "
" WHEN pg_catalog.pg_opfamily_is_visible(f.oid) \n "
" THEN format('%%I', f.opfname) \n "
" ELSE format('%%I.%%I', n.nspname, f.opfname) \n "
" END AS \" %s \" , \n "
" (SELECT \n "
" string_agg(format_type(oc.opcintype, -1), ', ') \n "
" FROM pg_opclass oc \n "
" WHERE oc.opcfamily = f.oid) \" %s \" " ,
gettext_noop ( " AM " ) ,
gettext_noop ( " Operator family " ) ,
gettext_noop ( " Applicable types " ) ) ;
if ( verbose )
appendPQExpBuffer ( & buf ,
" , \n pg_catalog.pg_get_userbyid(f.opfowner) AS \" %s \" \n " ,
gettext_noop ( " Owner " ) ) ;
appendPQExpBuffer ( & buf ,
" \n FROM pg_catalog.pg_opfamily f \n "
" LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod \n "
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace \n "
) ;
if ( access_method_pattern )
have_where = processSQLNamePattern ( pset . db , & buf , access_method_pattern ,
false , false , NULL , " am.amname " , NULL , NULL ) ;
if ( type_pattern )
{
appendPQExpBuffer ( & buf ,
" \n %s EXISTS ( \n "
" SELECT 1 \n "
" FROM pg_type t \n "
" JOIN pg_opclass oc ON oc.opcintype = t.oid \n "
" WHERE oc.opcfamily = f.oid " ,
have_where ? " AND " : " WHERE " ) ;
processSQLNamePattern ( pset . db , & buf , type_pattern , true , false ,
NULL , " t.typname " , NULL , NULL ) ;
appendPQExpBuffer ( & buf , " ) " ) ;
}
appendPQExpBufferStr ( & buf , " ORDER BY 1, 2; " ) ;
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
myopt . title = _ ( " List of operator families " ) ;
myopt . translate_header = true ;
myopt . translate_columns = translate_columns ;
myopt . n_translate_columns = lengthof ( translate_columns ) ;
printQuery ( res , & myopt , pset . queryFout , false , pset . logfile ) ;
PQclear ( res ) ;
return true ;
}
/*
* \ dAo
* Lists operators of operator families
*
* Takes an optional regexps to filter by index access method and operator
* family .
*/
bool
listOpFamilyOperators ( const char * access_method_pattern ,
const char * family_pattern , bool verbose )
{
PQExpBufferData buf ;
PGresult * res ;
printQueryOpt myopt = pset . popt ;
bool have_where = false ;
static const bool translate_columns [ ] = { false , false , false , false , false ,
false , false , true , false } ;
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
" SELECT \n "
" am.amname AS \" %s \" , \n "
" CASE \n "
" WHEN pg_catalog.pg_opfamily_is_visible(of.oid) \n "
" THEN format('%%I', of.opfname) \n "
" ELSE format('%%I.%%I', nsf.nspname, of.opfname) \n "
" END AS \" %s \" , \n "
" format ('%%s (%%s, %%s)', \n "
" CASE \n "
" WHEN pg_catalog.pg_operator_is_visible(op.oid) \n "
" THEN op.oprname::pg_catalog.text \n "
" ELSE o.amopopr::pg_catalog.regoper::pg_catalog.text \n "
" END, \n "
" pg_catalog.format_type(o.amoplefttype, NULL), \n "
" pg_catalog.format_type(o.amoprighttype, NULL) \n "
" ) AS \" %s \" \n " ,
gettext_noop ( " AM " ) ,
gettext_noop ( " Opfamily Name " ) ,
gettext_noop ( " Operator " ) ) ;
if ( verbose )
appendPQExpBuffer ( & buf ,
" , o.amopstrategy AS \" %s \" , \n "
" CASE o.amoppurpose \n "
" WHEN 'o' THEN '%s' \n "
" WHEN 's' THEN '%s' \n "
" END AS \" %s \" , \n "
" ofs.opfname AS \" %s \" \n " ,
gettext_noop ( " Strategy " ) ,
gettext_noop ( " ordering " ) ,
gettext_noop ( " search " ) ,
gettext_noop ( " Purpose " ) ,
gettext_noop ( " Sort opfamily " ) ) ;
appendPQExpBuffer ( & buf ,
" FROM pg_catalog.pg_amop o \n "
" LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr \n "
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily \n "
" LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod \n "
" LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid \n " ) ;
if ( verbose )
appendPQExpBuffer ( & buf ,
" LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily \n " ) ;
if ( access_method_pattern )
have_where = processSQLNamePattern ( pset . db , & buf , access_method_pattern ,
false , false , NULL , " am.amname " ,
NULL , NULL ) ;
if ( family_pattern )
processSQLNamePattern ( pset . db , & buf , family_pattern , have_where , false ,
" nsf.nspname " , " of.opfname " , NULL , NULL ) ;
appendPQExpBufferStr ( & buf , " ORDER BY 1, 2, o.amopstrategy, 3; " ) ;
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
myopt . title = _ ( " List of operators of operator families " ) ;
myopt . translate_header = true ;
myopt . translate_columns = translate_columns ;
myopt . n_translate_columns = lengthof ( translate_columns ) ;
printQuery ( res , & myopt , pset . queryFout , false , pset . logfile ) ;
PQclear ( res ) ;
return true ;
}
/*
* \ dAp
* Lists procedures of operator families
*
* Takes an optional regexps to filter by index access method and operator
* family .
*/
bool
listOpFamilyProcedures ( const char * access_method_pattern ,
const char * family_pattern )
{
PQExpBufferData buf ;
PGresult * res ;
printQueryOpt myopt = pset . popt ;
bool have_where = false ;
static const bool translate_columns [ ] = { false , false , false , false , false , false , false } ;
initPQExpBuffer ( & buf ) ;
printfPQExpBuffer ( & buf ,
" SELECT DISTINCT \n "
" am.amname AS \" %s \" , \n "
" CASE \n "
" WHEN pg_catalog.pg_opfamily_is_visible(of.oid) \n "
" THEN format('%%I', of.opfname) \n "
" ELSE format('%%I.%%I', ns.nspname, of.opfname) \n "
" END AS \" %s \" , \n "
" pg_catalog.format_type(ap.amproclefttype, NULL) AS \" %s \" , \n "
" pg_catalog.format_type(ap.amprocrighttype, NULL) AS \" %s \" , \n "
" ap.amprocnum AS \" %s \" \n , "
" p.proname AS \" %s \" \n " ,
gettext_noop ( " AM " ) ,
gettext_noop ( " Operator family " ) ,
gettext_noop ( " Left arg type " ) ,
gettext_noop ( " Right arg type " ) ,
gettext_noop ( " Number " ) ,
gettext_noop ( " Proc name " ) ) ;
appendPQExpBuffer ( & buf ,
" FROM pg_catalog.pg_amproc ap \n "
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily \n "
" LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod \n "
" LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid \n "
" LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid \n " ) ;
if ( access_method_pattern )
have_where = processSQLNamePattern ( pset . db , & buf , access_method_pattern ,
false , false , NULL , " am.amname " ,
NULL , NULL ) ;
if ( family_pattern )
processSQLNamePattern ( pset . db , & buf , family_pattern , have_where , false ,
" ns.nspname " , " of.opfname " , NULL , NULL ) ;
appendPQExpBufferStr ( & buf ,
" ORDER BY 1, 2, 3, 4, 5; " ) ;
res = PSQLexec ( buf . data ) ;
termPQExpBuffer ( & buf ) ;
if ( ! res )
return false ;
myopt . nullPrint = NULL ;
myopt . title = _ ( " List of procedures of operator families " ) ;
myopt . translate_header = true ;
myopt . translate_columns = translate_columns ;
myopt . n_translate_columns = lengthof ( translate_columns ) ;
printQuery ( res , & myopt , pset . queryFout , false , pset . logfile ) ;
PQclear ( res ) ;
return true ;
}