Show opclass and opfamily related information in psql
authorAlexander Korotkov
Sun, 8 Mar 2020 10:32:25 +0000 (13:32 +0300)
committerAlexander Korotkov
Sun, 8 Mar 2020 10:33:16 +0000 (13:33 +0300)
This commit provides psql commands for listing operator classes, operator
families and its contents in psql.  New commands will be useful for exploring
capabilities of both builtin opclasses/opfamilies as well as
opclasses/opfamilies defined in extensions.

Discussion: https://postgr.es/m/1529675324.14193.5.camel%40postgrespro.ru
Author: Sergey Cherkashin, Nikita Glukhov, Alexander Korotkov
Reviewed-by: Michael Paquier, Alvaro Herrera, Arthur Zakirov
Reviewed-by: Kyotaro Horiguchi, Andres Freund
doc/src/sgml/ref/psql-ref.sgml
src/bin/psql/command.c
src/bin/psql/describe.c
src/bin/psql/describe.h
src/bin/psql/help.c
src/bin/psql/tab-complete.c
src/test/regress/expected/psql.out
src/test/regress/sql/psql.sql

index 20ba10516066d6c515281cdf2baf28eb03aadb0f..67ecec27cf909026e066e6c438fa05267f1a7437 100644 (file)
@@ -1231,6 +1231,97 @@ testdb=>
         
       
 
+      
+        
+          \dAc[+]
+            [access-method-pattern
+              [input-type-pattern]]
+          
+        
+        
+        
+        Lists operator classes
+        (see ).
+        If access-method-patttern
+        is specified, only operator classes associated with access methods whose
+        names match pattern are listed.
+        If input-type-pattern
+        is specified, only operator classes associated with input types whose
+        names match the pattern are listed.
+        If + is appended to the command name, each operator
+        class is listed with its associated operator family and owner.
+        
+        
+      
+
+      
+        
+          \dAf[+]
+            [access-method-pattern
+              [input-type-pattern]]
+          
+        
+        
+        
+        Lists operator families
+        (see ).
+        If access-method-patttern
+        is specified, only operator families associated with access methods whose
+        names match pattern are listed.
+        If input-type-pattern
+        is specified, only operator families associated with input types whose
+        names match the pattern are listed.
+        If + is appended to the command name, each operator
+        family is listed with its owner.
+        
+        
+      
+
+      
+        
+          \dAo[+]
+            [access-method-pattern
+              [operator-family-pattern]]
+          
+        
+
+        
+        
+        Lists operators associated with operator families
+        ().
+        If access-method-patttern
+        is specified, only members of operator families associated with access
+        methods whose names match pattern are listed.
+        If input-type-pattern
+        is specified, only memeber of operator families whose names match the
+        pattern are listed.
+        If + is appended to the command name, each operator
+        is listed with its strategy number, purpose and sort operator family.
+        
+        
+      
+
+      
+        
+          \dAp[+]
+            [access-method-pattern
+              [operator-family-pattern]]
+          
+        
+        
+        
+        Lists procedures associated with operator families
+        ().
+        If access-method-patttern
+        is specified, only members of operator families associated with access
+        methods whose names match pattern are listed.
+        If input-type-pattern
+        is specified, only memeber of operator families whose names match the
+        pattern are listed.
+        
+        
+      
+
       
         \db[+] [ pattern ]
 
index e111cee5568e5e456f06d1e81c3a1cb5a9a68e24..abb18a19c23104646466c19022ad1d266f2c3e5a 100644 (file)
@@ -721,7 +721,38 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
                    success = listTables("tvmsE", NULL, show_verbose, show_system);
                break;
            case 'A':
-               success = describeAccessMethods(pattern, show_verbose);
+               {
+                   char       *pattern2 = NULL;
+
+                   if (pattern && cmd[2] != '\0' && cmd[2] != '+')
+                       pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+
+                   switch (cmd[2])
+                   {
+                       case '\0':
+                       case '+':
+                           success = describeAccessMethods(pattern, show_verbose);
+                           break;
+                       case 'c':
+                           success = listOperatorClasses(pattern, pattern2, show_verbose);
+                           break;
+                       case 'f':
+                           success = listOperatorFamilies(pattern, pattern2, show_verbose);
+                           break;
+                       case 'o':
+                           success = listOpFamilyOperators(pattern, pattern2, show_verbose);
+                           break;
+                       case 'p':
+                           success = listOpFamilyProcedures(pattern, pattern2);
+                           break;
+                       default:
+                           status = PSQL_CMD_UNKNOWN;
+                           break;
+                   }
+
+                   if (pattern2)
+                       free(pattern2);
+               }
                break;
            case 'a':
                success = describeAggregates(pattern, show_verbose, show_system);
index f3c7eb96fa690cd432fdb56d10c52f8dddf3b471..109245fea78c185201638f7c0bf68476da884f56 100644 (file)
@@ -14,6 +14,7 @@
 
 #include 
 
+#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,
+                     "\nFROM 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,
+                     "\nFROM 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;
+}
index 20dbfd20f0fb679904397029a36abfeac43be2ae..35c50e3bcd6cd3e00d35fe4c1ada334249cc9961 100644 (file)
@@ -114,4 +114,23 @@ bool       describePublications(const char *pattern);
 /* \dRs */
 bool       describeSubscriptions(const char *pattern, bool verbose);
 
+/* \dAc */
+extern bool listOperatorClasses(const char *access_method_pattern,
+                               const char *opclass_pattern,
+                               bool verbose);
+
+/* \dAf */
+extern bool listOperatorFamilies(const char *access_method_pattern,
+                                const char *opclass_pattern,
+                                bool verbose);
+
+/* \dAo */
+extern bool listOpFamilyOperators(const char *accessMethod_pattern,
+                                 const char *family_pattern, bool verbose);
+
+/* \dAp */
+extern bool listOpFamilyProcedures(const char *access_method_pattern,
+                                  const char *family_pattern);
+
+
 #endif                         /* DESCRIBE_H */
index 1f1f7784261a83ad11c9924cb4daae3e49911555..9a18cb3059492589990b92b3e8b404570c892012 100644 (file)
@@ -227,6 +227,10 @@ slashUsage(unsigned short int pager)
    fprintf(output, _("  \\d[S+]  NAME           describe table, view, sequence, or index\n"));
    fprintf(output, _("  \\da[S]  [PATTERN]      list aggregates\n"));
    fprintf(output, _("  \\dA[+]  [PATTERN]      list access methods\n"));
+   fprintf(output, _("  \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n"));
+   fprintf(output, _("  \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n"));
+   fprintf(output, _("  \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n"));
+   fprintf(output, _("  \\dAp    [AMPTRN [OPFPTRN]] list procedures of operator families\n"));
    fprintf(output, _("  \\db[+]  [PATTERN]      list tablespaces\n"));
    fprintf(output, _("  \\dc[S+] [PATTERN]      list conversions\n"));
    fprintf(output, _("  \\dC[+]  [PATTERN]      list casts\n"));
index 17b1f299b431e24e322cf2deadabb40cf6fcb4d2..174c3db62309fc50361489aeaddc0566131f77b1 100644 (file)
@@ -510,6 +510,13 @@ static const SchemaQuery Query_for_list_of_partitioned_relations = {
    .result = "pg_catalog.quote_ident(c.relname)",
 };
 
+static const SchemaQuery Query_for_list_of_operator_families = {
+   .catname = "pg_catalog.pg_opfamily c",
+   .viscondition = "pg_catalog.pg_opfamily_is_visible(c.oid)",
+   .namespace = "c.opfnamespace",
+   .result = "pg_catalog.quote_ident(c.opfname)",
+};
+
 /* Relations supporting INSERT, UPDATE or DELETE */
 static const SchemaQuery Query_for_list_of_updatables = {
    .catname = "pg_catalog.pg_class c",
@@ -1462,7 +1469,8 @@ psql_completion(const char *text, int start, int end)
        "\\a",
        "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
        "\\copyright", "\\crosstabview",
-       "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
+       "\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
+       "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
        "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
        "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
        "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
@@ -3698,6 +3706,12 @@ psql_completion(const char *text, int start, int end)
    }
    else if (TailMatchesCS("\\da*"))
        COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
+   else if (TailMatchesCS("\\dAc*", MatchAny) ||
+            TailMatchesCS("\\dAf*", MatchAny))
+       COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
+   else if (TailMatchesCS("\\dAo*", MatchAny) ||
+            TailMatchesCS("\\dAp*", MatchAny))
+       COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_operator_families, NULL);
    else if (TailMatchesCS("\\dA*"))
        COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
    else if (TailMatchesCS("\\db*"))
index 242f817163e73c6ef905a0d83a80c72914512cfd..2423ae2f37f0ec0cef016b57bbb57c40a2a173e4 100644 (file)
@@ -4809,3 +4809,165 @@ Owning table: "pg_catalog.pg_statistic"
 Indexes:
     "pg_toast_2619_index" PRIMARY KEY, btree (chunk_id, chunk_seq)
 
+-- check printing info about access methods
+\dA
+List of access methods
+  Name  | Type  
+--------+-------
+ brin   | Index
+ btree  | Index
+ gin    | Index
+ gist   | Index
+ hash   | Index
+ heap   | Table
+ heap2  | Table
+ spgist | Index
+(8 rows)
+
+\dA *
+List of access methods
+  Name  | Type  
+--------+-------
+ brin   | Index
+ btree  | Index
+ gin    | Index
+ gist   | Index
+ hash   | Index
+ heap   | Table
+ heap2  | Table
+ spgist | Index
+(8 rows)
+
+\dA h*
+List of access methods
+ Name  | Type  
+-------+-------
+ hash  | Index
+ heap  | Table
+ heap2 | Table
+(3 rows)
+
+\dA foo
+List of access methods
+ Name | Type 
+------+------
+(0 rows)
+
+\dA foo bar
+List of access methods
+ Name | Type 
+------+------
+(0 rows)
+
+\dA: extra argument "bar" ignored
+\dA+
+                             List of access methods
+  Name  | Type  |       Handler        |              Description               
+--------+-------+----------------------+----------------------------------------
+ brin   | Index | brinhandler          | block range index (BRIN) access method
+ btree  | Index | bthandler            | b-tree index access method
+ gin    | Index | ginhandler           | GIN index access method
+ gist   | Index | gisthandler          | GiST index access method
+ hash   | Index | hashhandler          | hash index access method
+ heap   | Table | heap_tableam_handler | heap table access method
+ heap2  | Table | heap_tableam_handler | 
+ spgist | Index | spghandler           | SP-GiST index access method
+(8 rows)
+
+\dA+ *
+                             List of access methods
+  Name  | Type  |       Handler        |              Description               
+--------+-------+----------------------+----------------------------------------
+ brin   | Index | brinhandler          | block range index (BRIN) access method
+ btree  | Index | bthandler            | b-tree index access method
+ gin    | Index | ginhandler           | GIN index access method
+ gist   | Index | gisthandler          | GiST index access method
+ hash   | Index | hashhandler          | hash index access method
+ heap   | Table | heap_tableam_handler | heap table access method
+ heap2  | Table | heap_tableam_handler | 
+ spgist | Index | spghandler           | SP-GiST index access method
+(8 rows)
+
+\dA+ h*
+                     List of access methods
+ Name  | Type  |       Handler        |       Description        
+-------+-------+----------------------+--------------------------
+ hash  | Index | hashhandler          | hash index access method
+ heap  | Table | heap_tableam_handler | heap table access method
+ heap2 | Table | heap_tableam_handler | 
+(3 rows)
+
+\dA+ foo
+       List of access methods
+ Name | Type | Handler | Description 
+------+------+---------+-------------
+(0 rows)
+
+\dAc brin pg*.oid*
+                   List of operator classes
+  AM  | Input type | Storage type | Operator class | Default? 
+------+------------+--------------+----------------+----------
+ brin | oid        |              | oid_minmax_ops | yes
+(1 row)
+
+\dAf spgist
+          List of operator families
+   AM   | Operator family | Applicable types 
+--------+-----------------+------------------
+ spgist | box_ops         | box
+ spgist | kd_point_ops    | point
+ spgist | network_ops     | inet
+ spgist | poly_ops        | polygon
+ spgist | quad_point_ops  | point
+ spgist | range_ops       | anyrange
+ spgist | text_ops        | text
+(7 rows)
+
+\dAf btree int4
+              List of operator families
+  AM   | Operator family |     Applicable types      
+-------+-----------------+---------------------------
+ btree | integer_ops     | smallint, integer, bigint
+(1 row)
+
+\dAo brin uuid_minmax_ops
+  List of operators of operator families
+  AM  |  Opfamily Name  |    Operator     
+------+-----------------+-----------------
+ brin | uuid_minmax_ops | < (uuid, uuid)
+ brin | uuid_minmax_ops | <= (uuid, uuid)
+ brin | uuid_minmax_ops | = (uuid, uuid)
+ brin | uuid_minmax_ops | >= (uuid, uuid)
+ brin | uuid_minmax_ops | > (uuid, uuid)
+(5 rows)
+
+\dAo * pg_catalog.jsonb_path_ops
+   List of operators of operator families
+ AM  | Opfamily Name  |       Operator       
+-----+----------------+----------------------
+ gin | jsonb_path_ops | @> (jsonb, jsonb)
+ gin | jsonb_path_ops | @? (jsonb, jsonpath)
+ gin | jsonb_path_ops | @@ (jsonb, jsonpath)
+(3 rows)
+
+\dAp brin uuid_minmax_ops
+                          List of procedures of operator families
+  AM  | Operator family | Left arg type | Right arg type | Number |       Proc name        
+------+-----------------+---------------+----------------+--------+------------------------
+ brin | uuid_minmax_ops | uuid          | uuid           |      1 | brin_minmax_opcinfo
+ brin | uuid_minmax_ops | uuid          | uuid           |      2 | brin_minmax_add_value
+ brin | uuid_minmax_ops | uuid          | uuid           |      3 | brin_minmax_consistent
+ brin | uuid_minmax_ops | uuid          | uuid           |      4 | brin_minmax_union
+(4 rows)
+
+\dAp * pg_catalog.uuid_ops
+                        List of procedures of operator families
+  AM   | Operator family | Left arg type | Right arg type | Number |     Proc name      
+-------+-----------------+---------------+----------------+--------+--------------------
+ btree | uuid_ops        | uuid          | uuid           |      1 | uuid_cmp
+ btree | uuid_ops        | uuid          | uuid           |      2 | uuid_sortsupport
+ btree | uuid_ops        | uuid          | uuid           |      4 | btequalimage
+ hash  | uuid_ops        | uuid          | uuid           |      1 | uuid_hash
+ hash  | uuid_ops        | uuid          | uuid           |      2 | uuid_hash_extended
+(5 rows)
+
index 26a0bcf7181b3a723b936617811754f63394c6ce..3c876d26992702eaff9b887f0378bfe7108fca01 100644 (file)
@@ -1182,3 +1182,21 @@ drop role regress_partitioning_role;
 
 -- \d on toast table (use pg_statistic's toast table, which has a known name)
 \d pg_toast.pg_toast_2619
+
+-- check printing info about access methods
+\dA
+\dA *
+\dA h*
+\dA foo
+\dA foo bar
+\dA+
+\dA+ *
+\dA+ h*
+\dA+ foo
+\dAc brin pg*.oid*
+\dAf spgist
+\dAf btree int4
+\dAo brin uuid_minmax_ops
+\dAo * pg_catalog.jsonb_path_ops
+\dAp brin uuid_minmax_ops
+\dAp * pg_catalog.uuid_ops