18#include "catalog/pg_am_d.h"
19#include "catalog/pg_class_d.h"
20#include "catalog/pg_namespace_d.h"
117 .strict_names =
true,
118 .show_progress =
false,
120 .install_missing =
false,
121 .install_schema =
"pg_catalog",
122 .include = {NULL, 0},
123 .exclude = {NULL, 0},
128 .no_toast_expansion =
false,
129 .reconcile_toast =
true,
130 .on_error_stop =
false,
134 .parent_check =
false,
135 .rootdescend =
false,
136 .heapallindexed =
false,
137 .checkunique =
false,
138 .no_btree_expansion =
false
174"SELECT n.nspname, x.extversion FROM pg_catalog.pg_extension x"
175"\nJOIN pg_catalog.pg_namespace n ON x.extnamespace = n.oid"
176"\nWHERE x.extname = 'amcheck'";
189 const char *
datname,
bool force,
bool finished);
202 const char *initial_dbname);
207#define log_no_match(...) do { \
208 if (opts.strict_names) \
209 pg_log_error(__VA_ARGS__); \
211 pg_log_warning(__VA_ARGS__); \
214#define FREE_AND_SET_NULL(x) do { \
227 const char *latest_datname;
228 int parallel_workers;
237 static struct option long_options[] = {
282 const char *db = NULL;
283 const char *maintenance_db = NULL;
285 const char *host = NULL;
286 const char *
port = NULL;
299 while ((
c =
getopt_long(argc, argv,
"ad:D:eh:Hi:I:j:p:Pr:R:s:S:t:T:U:vwW",
300 long_options, &optindex)) != -1)
303 unsigned long optval;
404 pg_fatal(
"invalid argument for option %s",
"--skip");
408 optval = strtoul(
optarg, &endptr, 10);
409 if (endptr ==
optarg || *endptr !=
'\0' || errno != 0)
412 pg_fatal(
"start block out of bounds");
417 optval = strtoul(
optarg, &endptr, 10);
418 if (endptr ==
optarg || *endptr !=
'\0' || errno != 0)
421 pg_fatal(
"end block out of bounds");
453 pg_fatal(
"end block precedes start block");
467 pg_log_error(
"too many command-line arguments (first is \"%s\")",
487 pg_fatal(
"cannot specify a database name with --all");
488 cparams.
dbname = maintenance_db;
493 pg_fatal(
"cannot specify both a database name and database patterns");
504 if (cparams.
dbname == NULL)
506 if (getenv(
"PGDATABASE"))
507 cparams.
dbname = getenv(
"PGDATABASE");
508 else if (getenv(
"PGUSER"))
509 cparams.
dbname = getenv(
"PGUSER");
517 if (databases.
head == NULL)
528 for (cell = databases.
head; cell; cell = cell->
next)
532 const char *amcheck_schema = NULL;
558 install_sql =
psprintf(
"CREATE EXTENSION IF NOT EXISTS amcheck WITH SCHEMA %s",
588 pg_log_warning(
"skipping database \"%s\": amcheck is not installed",
596 pg_log_info(
"in database \"%s\": using amcheck version \"%s\" in schema \"%s\"",
599 strlen(amcheck_schema));
616 const char *amcheck_version =
PQgetvalue(result, 0, 1);
618 sscanf(amcheck_version,
"%d.%d.%d", &vmaj, &vmin, &vrev);
623 if ((vmaj == 1 && vmin < 4) || vmaj == 0)
625 pg_log_warning(
"option %s is not supported by amcheck version %s",
626 "--checkunique", amcheck_version);
654 log_no_match(
"no btree indexes to check matching \"%s\"",
657 log_no_match(
"no relations to check in schemas matching \"%s\"",
676 parallel_workers = 0;
677 for (cell = relations.
head; cell; cell = cell->
next)
701 latest_datname = NULL;
711 for (relprogress = 0, cell = relations.
head; cell; cell = cell->
next)
733 latest_datname,
false,
false);
810 progress_report(reltotal, relprogress, pagestotal, pageschecked, NULL,
true,
true);
846 "SELECT v.blkno, v.offnum, v.attnum, v.msg "
847 "FROM pg_catalog.pg_class c, %s.verify_heapam("
848 "\nrelation := c.oid, on_error_stop := %s, check_toast := %s, skip := '%s'",
860 "\n) v WHERE c.oid = %u "
861 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP),
888 "SELECT %s.bt_index_parent_check("
889 "index := c.oid, heapallindexed := %s, rootdescend := %s "
891 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
893 "AND c.oid = i.indexrelid "
894 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)
" "
895 "AND i.indisready AND i.indisvalid AND i.indislive",
903 "SELECT %s.bt_index_check("
904 "index := c.oid, heapallindexed := %s "
906 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
908 "AND c.oid = i.indexrelid "
909 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)
" "
910 "AND i.indisready AND i.indisvalid AND i.indislive",
938 pg_log_error(
"error sending command to database \"%s\": %s",
965 const char *severity;
978 if (severity == NULL)
980 if (strcmp(severity,
"FATAL") == 0)
982 if (strcmp(severity,
"PANIC") == 0)
1018 if (
c[0] ==
'\n' &&
c[1] !=
'\0')
1050 for (
i = 0;
i < ntups;
i++)
1061 printf(
_(
"heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n"),
1068 printf(
_(
"heap table \"%s.%s.%s\", block %s, offset %s:\n"),
1074 printf(
_(
"heap table \"%s.%s.%s\", block %s:\n"),
1079 printf(
_(
"heap table \"%s.%s.%s\":\n"),
1090 printf(
_(
"heap table \"%s.%s.%s\":\n"),
1145 pg_log_warning(
"btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d",
1159 printf(
_(
"btree index \"%s.%s.%s\":\n"),
1184 printf(
_(
"%s checks objects in a PostgreSQL database for corruption.\n\n"),
progname);
1187 printf(
_(
"\nTarget options:\n"));
1188 printf(
_(
" -a, --all check all databases\n"));
1189 printf(
_(
" -d, --database=PATTERN check matching database(s)\n"));
1190 printf(
_(
" -D, --exclude-database=PATTERN do NOT check matching database(s)\n"));
1191 printf(
_(
" -i, --index=PATTERN check matching index(es)\n"));
1192 printf(
_(
" -I, --exclude-index=PATTERN do NOT check matching index(es)\n"));
1193 printf(
_(
" -r, --relation=PATTERN check matching relation(s)\n"));
1194 printf(
_(
" -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n"));
1195 printf(
_(
" -s, --schema=PATTERN check matching schema(s)\n"));
1196 printf(
_(
" -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n"));
1197 printf(
_(
" -t, --table=PATTERN check matching table(s)\n"));
1198 printf(
_(
" -T, --exclude-table=PATTERN do NOT check matching table(s)\n"));
1199 printf(
_(
" --no-dependent-indexes do NOT expand list of relations to include indexes\n"));
1200 printf(
_(
" --no-dependent-toast do NOT expand list of relations to include TOAST tables\n"));
1201 printf(
_(
" --no-strict-names do NOT require patterns to match objects\n"));
1202 printf(
_(
"\nTable checking options:\n"));
1203 printf(
_(
" --exclude-toast-pointers do NOT follow relation TOAST pointers\n"));
1204 printf(
_(
" --on-error-stop stop checking at end of first corrupt page\n"));
1205 printf(
_(
" --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n"));
1206 printf(
_(
" --startblock=BLOCK begin checking table(s) at the given block number\n"));
1207 printf(
_(
" --endblock=BLOCK check table(s) only up to the given block number\n"));
1208 printf(
_(
"\nB-tree index checking options:\n"));
1209 printf(
_(
" --checkunique check unique constraint if index is unique\n"));
1210 printf(
_(
" --heapallindexed check that all heap tuples are found within indexes\n"));
1211 printf(
_(
" --parent-check check index parent/child relationships\n"));
1212 printf(
_(
" --rootdescend search from root page to refind tuples\n"));
1213 printf(
_(
"\nConnection options:\n"));
1214 printf(
_(
" -h, --host=HOSTNAME database server host or socket directory\n"));
1215 printf(
_(
" -p, --port=PORT database server port\n"));
1216 printf(
_(
" -U, --username=USERNAME user name to connect as\n"));
1217 printf(
_(
" -w, --no-password never prompt for password\n"));
1218 printf(
_(
" -W, --password force password prompt\n"));
1219 printf(
_(
" --maintenance-db=DBNAME alternate maintenance database\n"));
1220 printf(
_(
"\nOther options:\n"));
1221 printf(
_(
" -e, --echo show the commands being sent to the server\n"));
1222 printf(
_(
" -j, --jobs=NUM use this many concurrent connections to the server\n"));
1223 printf(
_(
" -P, --progress show progress information\n"));
1224 printf(
_(
" -v, --verbose write a lot of output\n"));
1225 printf(
_(
" -V, --version output version information, then exit\n"));
1226 printf(
_(
" --install-missing install missing extensions\n"));
1227 printf(
_(
" -?, --help show this help, then exit\n"));
1229 printf(
_(
"\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1230 printf(
_(
"%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
1245 const char *
datname,
bool force,
bool finished)
1247 int percent_rel = 0;
1248 int percent_pages = 0;
1249 char checked_rel[32];
1251 char checked_pages[32];
1252 char total_pages[32];
1263 if (relations_total)
1264 percent_rel = (int) (relations_checked * 100 / relations_total);
1266 percent_pages = (int) (relpages_checked * 100 / relpages_total);
1273#define VERBOSE_DATNAME_LENGTH 35
1283 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s"),
1284 (
int) strlen(total_rel),
1285 checked_rel, total_rel, percent_rel,
1286 (
int) strlen(total_pages),
1287 checked_pages, total_pages, percent_pages,
1294 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)"),
1295 (
int) strlen(total_rel),
1296 checked_rel, total_rel, percent_rel,
1297 (
int) strlen(total_pages),
1298 checked_pages, total_pages, percent_pages,
1300 truncate ?
"..." :
"",
1309 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%)"),
1310 (
int) strlen(total_rel),
1311 checked_rel, total_rel, percent_rel,
1312 (
int) strlen(total_pages),
1313 checked_pages, total_pages, percent_pages);
1319 if (!finished && isatty(fileno(stderr)))
1321 fputc(
'\r', stderr);
1325 fputc(
'\n', stderr);
1341 result = &pia->
data[pia->
len - 1];
1342 memset(result, 0,
sizeof(*result));
1368 pg_log_error(
"improper qualified name (too many dotted names): %s", pattern);
1401 pg_log_error(
"improper qualified name (too many dotted names): %s", pattern);
1430 int encoding,
bool heap_only,
bool btree_only)
1446 pg_log_error(
"improper relation name (too many dotted names): %s", pattern);
1546 have_values =
false;
1547 for (pattern_id = 0; pattern_id < pia->
len; pattern_id++)
1585 const char *initial_dbname)
1599 pg_log_info(
"including database \"%s\"", initial_dbname);
1635 "\ndatabase (datname) AS ("
1636 "\nSELECT d.datname "
1637 "FROM pg_catalog.pg_database d "
1638 "LEFT OUTER JOIN exclude_raw e "
1639 "ON d.datname ~ e.rgx "
1640 "\nWHERE d.datallowconn AND datconnlimit != -2 "
1641 "AND e.pattern_id IS NULL"
1650 "\ninclude_pat (pattern_id, checkable) AS ("
1651 "\nSELECT i.pattern_id, "
1653 "WHERE d IS NOT NULL"
1655 "\nFROM include_raw i "
1656 "LEFT OUTER JOIN database d "
1657 "ON d.datname ~ i.rgx"
1658 "\nGROUP BY i.pattern_id"
1668 "\nfiltered_databases (datname) AS ("
1669 "\nSELECT DISTINCT d.datname "
1673 " INNER JOIN include_raw i "
1674 "ON d.datname ~ i.rgx");
1681 "\nSELECT pattern_id, datname FROM ("
1682 "\nSELECT pattern_id, NULL::TEXT AS datname "
1684 "WHERE checkable = 0 "
1686 "\nSELECT NULL, datname "
1687 "FROM filtered_databases"
1688 ") AS combined_records"
1689 "\nORDER BY pattern_id NULLS LAST, datname");
1702 for (fatal =
false,
i = 0;
i < ntups;
i++)
1704 int pattern_id = -1;
1712 if (pattern_id >= 0)
1720 pg_fatal(
"internal error: received unexpected database pattern_id %d",
1722 log_no_match(
"no connectable databases to check matching \"%s\"",
1733 if (initial_dbname != NULL && strcmp(initial_dbname,
datname) == 0)
1784 have_values =
false;
1785 for (pattern_id = 0; pattern_id < pia->
len; pattern_id++)
1821 "\nSELECT NULL::INTEGER, NULL::TEXT, NULL::TEXT, "
1822 "NULL::TEXT, NULL::BOOLEAN, NULL::BOOLEAN "
1849 "\n%s (pattern_id, nsp_regex, rel_regex, heap_only, btree_only) AS ("
1850 "\nSELECT pattern_id, nsp_regex, rel_regex, heap_only, btree_only "
1852 "\nWHERE (r.db_regex IS NULL "
1858 " AND (r.nsp_regex IS NOT NULL"
1859 " OR r.rel_regex IS NOT NULL)"
1900 " include_raw (pattern_id, db_regex, nsp_regex, rel_regex, heap_only, btree_only) AS (");
1910 " exclude_raw (pattern_id, db_regex, nsp_regex, rel_regex, heap_only, btree_only) AS (");
1918 " relation (pattern_id, oid, nspname, relname, reltoastrelid, relpages, is_heap, is_btree) AS ("
1919 "\nSELECT DISTINCT ON (c.oid");
1925 "\nc.oid, n.nspname, c.relname, c.reltoastrelid, c.relpages, "
1926 "c.relam = %u AS is_heap, "
1927 "c.relam = %u AS is_btree"
1928 "\nFROM pg_catalog.pg_class c "
1929 "INNER JOIN pg_catalog.pg_namespace n "
1930 "ON c.relnamespace = n.oid",
1931 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1934 "\nINNER JOIN include_pat ip"
1935 "\nON (n.nspname ~ ip.nsp_regex OR ip.nsp_regex IS NULL)"
1936 "\nAND (c.relname ~ ip.rel_regex OR ip.rel_regex IS NULL)"
1937 "\nAND (c.relam = %u OR NOT ip.heap_only)"
1938 "\nAND (c.relam = %u OR NOT ip.btree_only)",
1939 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1942 "\nLEFT OUTER JOIN exclude_pat ep"
1943 "\nON (n.nspname ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
1944 "\nAND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
1945 "\nAND (c.relam = %u OR NOT ep.heap_only OR ep.rel_regex IS NULL)"
1946 "\nAND (c.relam = %u OR NOT ep.btree_only OR ep.rel_regex IS NULL)",
1947 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1976 " AND c.relam = %u "
1977 "AND c.relkind IN ("
1982 "AND c.relnamespace != %u",
1983 HEAP_TABLE_AM_OID, PG_TOAST_NAMESPACE);
1986 " AND c.relam IN (%u, %u)"
1987 "AND c.relkind IN ("
1993 "AND ((c.relam = %u AND c.relkind IN ("
1998 "(c.relam = %u AND c.relkind = "
2000 HEAP_TABLE_AM_OID, BTREE_AM_OID,
2001 HEAP_TABLE_AM_OID, BTREE_AM_OID);
2004 "\nORDER BY c.oid)");
2014 ", toast (oid, nspname, relname, relpages) AS ("
2015 "\nSELECT t.oid, 'pg_toast', t.relname, t.relpages"
2016 "\nFROM pg_catalog.pg_class t "
2017 "INNER JOIN relation r "
2018 "ON r.reltoastrelid = t.oid");
2021 "\nLEFT OUTER JOIN exclude_pat ep"
2022 "\nON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
2023 "\nAND (t.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
2024 "\nAND ep.heap_only"
2025 "\nWHERE ep.pattern_id IS NULL"
2026 "\nAND t.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP));
2038 ", index (oid, nspname, relname, relpages) AS ("
2039 "\nSELECT c.oid, r.nspname, c.relname, c.relpages "
2041 "\nINNER JOIN pg_catalog.pg_index i "
2042 "ON r.oid = i.indrelid "
2043 "INNER JOIN pg_catalog.pg_class c "
2044 "ON i.indexrelid = c.oid "
2045 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP));
2048 "\nINNER JOIN pg_catalog.pg_namespace n "
2049 "ON c.relnamespace = n.oid"
2050 "\nLEFT OUTER JOIN exclude_pat ep "
2051 "ON (n.nspname ~ ep.nsp_regex OR ep.nsp_regex IS NULL) "
2052 "AND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL) "
2054 "\nWHERE ep.pattern_id IS NULL");
2059 " AND c.relam = %u "
2064 " AND c.relnamespace != %u",
2065 PG_TOAST_NAMESPACE);
2077 ", toast_index (oid, nspname, relname, relpages) AS ("
2078 "\nSELECT c.oid, 'pg_toast', c.relname, c.relpages "
2080 "INNER JOIN pg_catalog.pg_index i "
2081 "ON t.oid = i.indrelid"
2082 "\nINNER JOIN pg_catalog.pg_class c "
2083 "ON i.indexrelid = c.oid "
2084 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP));
2087 "\nLEFT OUTER JOIN exclude_pat ep "
2088 "ON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL) "
2089 "AND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL) "
2090 "AND ep.btree_only "
2091 "WHERE ep.pattern_id IS NULL");
2110 "\nSELECT pattern_id, is_heap, is_btree, oid, nspname, relname, relpages "
2114 "\nSELECT pattern_id, is_heap, is_btree, "
2115 "NULL::OID AS oid, "
2116 "NULL::TEXT AS nspname, "
2117 "NULL::TEXT AS relname, "
2118 "NULL::INTEGER AS relpages"
2120 "WHERE pattern_id IS NOT NULL "
2123 "\nSELECT NULL::INTEGER AS pattern_id, "
2124 "is_heap, is_btree, oid, nspname, relname, relpages "
2130 "\nSELECT NULL::INTEGER AS pattern_id, TRUE AS is_heap, "
2131 "FALSE AS is_btree, oid, nspname, relname, relpages "
2137 "\nSELECT NULL::INTEGER AS pattern_id, FALSE AS is_heap, "
2138 "TRUE AS is_btree, oid, nspname, relname, relpages "
2144 "\nSELECT NULL::INTEGER AS pattern_id, FALSE AS is_heap, "
2145 "TRUE AS is_btree, oid, nspname, relname, relpages "
2146 "FROM toast_index");
2148 "\n) AS combined_records "
2149 "ORDER BY relpages DESC NULLS FIRST, oid");
2162 for (
i = 0;
i < ntups;
i++)
2164 int pattern_id = -1;
2165 bool is_heap =
false;
2168 const char *nspname = NULL;
2187 if (pattern_id >= 0)
2195 pg_fatal(
"internal error: received unexpected relation pattern_id %d",
2207 Assert((is_heap && !is_btree) || (is_btree && !is_heap));
Datum now(PG_FUNCTION_ARGS)
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
#define PG_TEXTDOMAIN(domain)
#define OidIsValid(objectId)
volatile sig_atomic_t CancelRequested
void setup_cancel_handler(void(*query_cancel_callback)(void))
void set_pglocale_pgservice(const char *argv0, const char *app)
void disconnectDatabase(PGconn *conn)
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
#define fprintf(file, fmt, msg)
static void PGresult * res
char * PQdb(const PGconn *conn)
PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
char * PQerrorMessage(const PGconn *conn)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
ExecStatusType PQresultStatus(const PGresult *res)
int PQntuples(const PGresult *res)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
char * PQresultErrorField(const PGresult *res, int fieldcode)
int PQsendQuery(PGconn *conn, const char *query)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
char * pg_strdup(const char *in)
void * pg_malloc0(size_t size)
void * pg_realloc(void *ptr, size_t size)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
#define optional_argument
if(TABLE==NULL||TABLE_index==NULL)
void pg_logging_increase_verbosity(void)
void pg_logging_init(const char *argv0)
#define pg_log_error(...)
#define pg_log_error_hint(...)
#define pg_log_warning_hint(...)
#define pg_log_warning_detail(...)
#define pg_log_error_detail(...)
char * pstrdup(const char *in)
void pfree(void *pointer)
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
ParallelSlotArray * ParallelSlotsSetup(int numslots, ConnParams *cparams, const char *progname, bool echo, const char *initcmd)
bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa)
ParallelSlot * ParallelSlotsGetIdle(ParallelSlotArray *sa, const char *dbname)
void ParallelSlotsTerminate(ParallelSlotArray *sa)
void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn)
static void ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler, void *context)
#define VERBOSE_DATNAME_LENGTH
static bool should_processing_continue(PGresult *res)
int main(int argc, char *argv[])
static void progress_report(uint64 relations_total, uint64 relations_checked, uint64 relpages_total, uint64 relpages_checked, const char *datname, bool force, bool finished)
static void append_rel_pattern_filtered_cte(PQExpBuffer buf, const char *raw, const char *filtered, PGconn *conn)
static AmcheckOptions opts
static void compile_database_list(PGconn *conn, SimplePtrList *databases, const char *initial_dbname)
struct DatabaseInfo DatabaseInfo
static void prepare_btree_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn)
static void help(const char *progname)
struct PatternInfoArray PatternInfoArray
static void append_database_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
static void append_rel_pattern_raw_cte(PQExpBuffer buf, const PatternInfoArray *pia, PGconn *conn)
static bool verify_heap_slot_handler(PGresult *res, PGconn *conn, void *context)
struct PatternInfo PatternInfo
static pg_time_t last_progress_report
#define FREE_AND_SET_NULL(x)
static void append_relation_pattern_helper(PatternInfoArray *pia, const char *pattern, int encoding, bool heap_only, bool btree_only)
static char * indent_lines(const char *str)
static const char *const amcheck_sql
struct RelationInfo RelationInfo
static void run_command(ParallelSlot *slot, const char *sql)
static void append_heap_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
#define log_no_match(...)
static void append_schema_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
static bool verify_btree_slot_handler(PGresult *res, PGconn *conn, void *context)
struct AmcheckOptions AmcheckOptions
static bool progress_since_last_stderr
static const char * progname
static void append_relation_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
static bool append_db_pattern_cte(PQExpBuffer buf, const PatternInfoArray *pia, PGconn *conn, bool inclusive)
static void prepare_heap_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn)
static bool all_checks_pass
static void compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, const DatabaseInfo *dat, uint64 *pagecount)
static void append_btree_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
static PatternInfo * extend_pattern_info_array(PatternInfoArray *pia)
static PGconn * connectDatabase(const char *dbname, const char *connection_string, const char *pghost, const char *pgport, const char *pguser, trivalue prompt_password, bool fail_on_error)
static void executeCommand(PGconn *conn, const char *query)
static PGresult * executeQuery(PGconn *conn, const char *query)
PGDLLIMPORT char * optarg
#define pg_log_warning(...)
int pg_strcasecmp(const char *s1, const char *s2)
const char * get_progname(const char *argv0)
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
#define PG_DIAG_SEVERITY_NONLOCALIZED
void initPQExpBuffer(PQExpBuffer str)
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
char * psprintf(const char *fmt,...)
void simple_ptr_list_append(SimplePtrList *list, void *ptr)
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
void patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf, PQExpBuffer namebuf, const char *pattern, bool force_escape, bool want_literal_dbname, int *dotcnt)
const DatabaseInfo * datinfo
struct SimplePtrListCell * next
enum trivalue prompt_password
const char * get_user_name_or_exit(const char *progname)