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",
597 pg_log_info(
"in database \"%s\": using amcheck version \"%s\" in schema \"%s\"",
600 strlen(amcheck_schema));
617 const char *amcheck_version =
PQgetvalue(result, 0, 1);
619 sscanf(amcheck_version,
"%d.%d.%d", &vmaj, &vmin, &vrev);
624 if ((vmaj == 1 && vmin < 4) || vmaj == 0)
626 pg_log_warning(
"option %s is not supported by amcheck version %s",
627 "--checkunique", amcheck_version);
655 log_no_match(
"no btree indexes to check matching \"%s\"",
658 log_no_match(
"no relations to check in schemas matching \"%s\"",
677 parallel_workers = 0;
678 for (cell = relations.
head; cell; cell = cell->
next)
702 latest_datname = NULL;
712 for (relprogress = 0, cell = relations.
head; cell; cell = cell->
next)
734 latest_datname,
false,
false);
811 progress_report(reltotal, relprogress, pagestotal, pageschecked, NULL,
true,
true);
847 "SELECT v.blkno, v.offnum, v.attnum, v.msg "
848 "FROM pg_catalog.pg_class c, %s.verify_heapam("
849 "\nrelation := c.oid, on_error_stop := %s, check_toast := %s, skip := '%s'",
861 "\n) v WHERE c.oid = %u "
862 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP),
889 "SELECT %s.bt_index_parent_check("
890 "index := c.oid, heapallindexed := %s, rootdescend := %s "
892 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
894 "AND c.oid = i.indexrelid "
895 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)
" "
896 "AND i.indisready AND i.indisvalid AND i.indislive",
904 "SELECT %s.bt_index_check("
905 "index := c.oid, heapallindexed := %s "
907 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
909 "AND c.oid = i.indexrelid "
910 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)
" "
911 "AND i.indisready AND i.indisvalid AND i.indislive",
939 pg_log_error(
"error sending command to database \"%s\": %s",
966 const char *severity;
979 if (severity == NULL)
981 if (strcmp(severity,
"FATAL") == 0)
983 if (strcmp(severity,
"PANIC") == 0)
1019 if (
c[0] ==
'\n' &&
c[1] !=
'\0')
1051 for (
i = 0;
i < ntups;
i++)
1062 printf(
_(
"heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n"),
1069 printf(
_(
"heap table \"%s.%s.%s\", block %s, offset %s:\n"),
1075 printf(
_(
"heap table \"%s.%s.%s\", block %s:\n"),
1080 printf(
_(
"heap table \"%s.%s.%s\":\n"),
1091 printf(
_(
"heap table \"%s.%s.%s\":\n"),
1146 pg_log_warning(
"btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d",
1160 printf(
_(
"btree index \"%s.%s.%s\":\n"),
1185 printf(
_(
"%s checks objects in a PostgreSQL database for corruption.\n\n"),
progname);
1188 printf(
_(
"\nTarget options:\n"));
1189 printf(
_(
" -a, --all check all databases\n"));
1190 printf(
_(
" -d, --database=PATTERN check matching database(s)\n"));
1191 printf(
_(
" -D, --exclude-database=PATTERN do NOT check matching database(s)\n"));
1192 printf(
_(
" -i, --index=PATTERN check matching index(es)\n"));
1193 printf(
_(
" -I, --exclude-index=PATTERN do NOT check matching index(es)\n"));
1194 printf(
_(
" -r, --relation=PATTERN check matching relation(s)\n"));
1195 printf(
_(
" -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n"));
1196 printf(
_(
" -s, --schema=PATTERN check matching schema(s)\n"));
1197 printf(
_(
" -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n"));
1198 printf(
_(
" -t, --table=PATTERN check matching table(s)\n"));
1199 printf(
_(
" -T, --exclude-table=PATTERN do NOT check matching table(s)\n"));
1200 printf(
_(
" --no-dependent-indexes do NOT expand list of relations to include indexes\n"));
1201 printf(
_(
" --no-dependent-toast do NOT expand list of relations to include TOAST tables\n"));
1202 printf(
_(
" --no-strict-names do NOT require patterns to match objects\n"));
1203 printf(
_(
"\nTable checking options:\n"));
1204 printf(
_(
" --exclude-toast-pointers do NOT follow relation TOAST pointers\n"));
1205 printf(
_(
" --on-error-stop stop checking at end of first corrupt page\n"));
1206 printf(
_(
" --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n"));
1207 printf(
_(
" --startblock=BLOCK begin checking table(s) at the given block number\n"));
1208 printf(
_(
" --endblock=BLOCK check table(s) only up to the given block number\n"));
1209 printf(
_(
"\nB-tree index checking options:\n"));
1210 printf(
_(
" --checkunique check unique constraint if index is unique\n"));
1211 printf(
_(
" --heapallindexed check that all heap tuples are found within indexes\n"));
1212 printf(
_(
" --parent-check check index parent/child relationships\n"));
1213 printf(
_(
" --rootdescend search from root page to refind tuples\n"));
1214 printf(
_(
"\nConnection options:\n"));
1215 printf(
_(
" -h, --host=HOSTNAME database server host or socket directory\n"));
1216 printf(
_(
" -p, --port=PORT database server port\n"));
1217 printf(
_(
" -U, --username=USERNAME user name to connect as\n"));
1218 printf(
_(
" -w, --no-password never prompt for password\n"));
1219 printf(
_(
" -W, --password force password prompt\n"));
1220 printf(
_(
" --maintenance-db=DBNAME alternate maintenance database\n"));
1221 printf(
_(
"\nOther options:\n"));
1222 printf(
_(
" -e, --echo show the commands being sent to the server\n"));
1223 printf(
_(
" -j, --jobs=NUM use this many concurrent connections to the server\n"));
1224 printf(
_(
" -P, --progress show progress information\n"));
1225 printf(
_(
" -v, --verbose write a lot of output\n"));
1226 printf(
_(
" -V, --version output version information, then exit\n"));
1227 printf(
_(
" --install-missing install missing extensions\n"));
1228 printf(
_(
" -?, --help show this help, then exit\n"));
1230 printf(
_(
"\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1231 printf(
_(
"%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
1246 const char *
datname,
bool force,
bool finished)
1248 int percent_rel = 0;
1249 int percent_pages = 0;
1250 char checked_rel[32];
1252 char checked_pages[32];
1253 char total_pages[32];
1264 if (relations_total)
1265 percent_rel = (int) (relations_checked * 100 / relations_total);
1267 percent_pages = (int) (relpages_checked * 100 / relpages_total);
1274#define VERBOSE_DATNAME_LENGTH 35
1284 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s"),
1285 (
int) strlen(total_rel),
1286 checked_rel, total_rel, percent_rel,
1287 (
int) strlen(total_pages),
1288 checked_pages, total_pages, percent_pages,
1295 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)"),
1296 (
int) strlen(total_rel),
1297 checked_rel, total_rel, percent_rel,
1298 (
int) strlen(total_pages),
1299 checked_pages, total_pages, percent_pages,
1301 truncate ?
"..." :
"",
1310 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%)"),
1311 (
int) strlen(total_rel),
1312 checked_rel, total_rel, percent_rel,
1313 (
int) strlen(total_pages),
1314 checked_pages, total_pages, percent_pages);
1320 if (!finished && isatty(fileno(stderr)))
1322 fputc(
'\r', stderr);
1326 fputc(
'\n', stderr);
1342 result = &pia->
data[pia->
len - 1];
1343 memset(result, 0,
sizeof(*result));
1369 pg_log_error(
"improper qualified name (too many dotted names): %s", pattern);
1402 pg_log_error(
"improper qualified name (too many dotted names): %s", pattern);
1431 int encoding,
bool heap_only,
bool btree_only)
1447 pg_log_error(
"improper relation name (too many dotted names): %s", pattern);
1547 have_values =
false;
1548 for (pattern_id = 0; pattern_id < pia->
len; pattern_id++)
1586 const char *initial_dbname)
1600 pg_log_info(
"including database \"%s\"", initial_dbname);
1636 "\ndatabase (datname) AS ("
1637 "\nSELECT d.datname "
1638 "FROM pg_catalog.pg_database d "
1639 "LEFT OUTER JOIN exclude_raw e "
1640 "ON d.datname ~ e.rgx "
1641 "\nWHERE d.datallowconn AND datconnlimit != -2 "
1642 "AND e.pattern_id IS NULL"
1651 "\ninclude_pat (pattern_id, checkable) AS ("
1652 "\nSELECT i.pattern_id, "
1654 "WHERE d IS NOT NULL"
1656 "\nFROM include_raw i "
1657 "LEFT OUTER JOIN database d "
1658 "ON d.datname ~ i.rgx"
1659 "\nGROUP BY i.pattern_id"
1669 "\nfiltered_databases (datname) AS ("
1670 "\nSELECT DISTINCT d.datname "
1674 " INNER JOIN include_raw i "
1675 "ON d.datname ~ i.rgx");
1682 "\nSELECT pattern_id, datname FROM ("
1683 "\nSELECT pattern_id, NULL::TEXT AS datname "
1685 "WHERE checkable = 0 "
1687 "\nSELECT NULL, datname "
1688 "FROM filtered_databases"
1689 ") AS combined_records"
1690 "\nORDER BY pattern_id NULLS LAST, datname");
1703 for (fatal =
false,
i = 0;
i < ntups;
i++)
1705 int pattern_id = -1;
1713 if (pattern_id >= 0)
1721 pg_fatal(
"internal error: received unexpected database pattern_id %d",
1723 log_no_match(
"no connectable databases to check matching \"%s\"",
1734 if (initial_dbname != NULL && strcmp(initial_dbname,
datname) == 0)
1785 have_values =
false;
1786 for (pattern_id = 0; pattern_id < pia->
len; pattern_id++)
1822 "\nSELECT NULL::INTEGER, NULL::TEXT, NULL::TEXT, "
1823 "NULL::TEXT, NULL::BOOLEAN, NULL::BOOLEAN "
1850 "\n%s (pattern_id, nsp_regex, rel_regex, heap_only, btree_only) AS ("
1851 "\nSELECT pattern_id, nsp_regex, rel_regex, heap_only, btree_only "
1853 "\nWHERE (r.db_regex IS NULL "
1859 " AND (r.nsp_regex IS NOT NULL"
1860 " OR r.rel_regex IS NOT NULL)"
1901 " include_raw (pattern_id, db_regex, nsp_regex, rel_regex, heap_only, btree_only) AS (");
1911 " exclude_raw (pattern_id, db_regex, nsp_regex, rel_regex, heap_only, btree_only) AS (");
1919 " relation (pattern_id, oid, nspname, relname, reltoastrelid, relpages, is_heap, is_btree) AS ("
1920 "\nSELECT DISTINCT ON (c.oid");
1926 "\nc.oid, n.nspname, c.relname, c.reltoastrelid, c.relpages, "
1927 "c.relam = %u AS is_heap, "
1928 "c.relam = %u AS is_btree"
1929 "\nFROM pg_catalog.pg_class c "
1930 "INNER JOIN pg_catalog.pg_namespace n "
1931 "ON c.relnamespace = n.oid",
1932 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1935 "\nINNER JOIN include_pat ip"
1936 "\nON (n.nspname ~ ip.nsp_regex OR ip.nsp_regex IS NULL)"
1937 "\nAND (c.relname ~ ip.rel_regex OR ip.rel_regex IS NULL)"
1938 "\nAND (c.relam = %u OR NOT ip.heap_only)"
1939 "\nAND (c.relam = %u OR NOT ip.btree_only)",
1940 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1943 "\nLEFT OUTER JOIN exclude_pat ep"
1944 "\nON (n.nspname ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
1945 "\nAND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
1946 "\nAND (c.relam = %u OR NOT ep.heap_only OR ep.rel_regex IS NULL)"
1947 "\nAND (c.relam = %u OR NOT ep.btree_only OR ep.rel_regex IS NULL)",
1948 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1977 " AND c.relam = %u "
1978 "AND c.relkind IN ("
1983 "AND c.relnamespace != %u",
1984 HEAP_TABLE_AM_OID, PG_TOAST_NAMESPACE);
1987 " AND c.relam IN (%u, %u)"
1988 "AND c.relkind IN ("
1994 "AND ((c.relam = %u AND c.relkind IN ("
1999 "(c.relam = %u AND c.relkind = "
2001 HEAP_TABLE_AM_OID, BTREE_AM_OID,
2002 HEAP_TABLE_AM_OID, BTREE_AM_OID);
2005 "\nORDER BY c.oid)");
2015 ", toast (oid, nspname, relname, relpages) AS ("
2016 "\nSELECT t.oid, 'pg_toast', t.relname, t.relpages"
2017 "\nFROM pg_catalog.pg_class t "
2018 "INNER JOIN relation r "
2019 "ON r.reltoastrelid = t.oid");
2022 "\nLEFT OUTER JOIN exclude_pat ep"
2023 "\nON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
2024 "\nAND (t.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
2025 "\nAND ep.heap_only"
2026 "\nWHERE ep.pattern_id IS NULL"
2027 "\nAND t.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP));
2039 ", index (oid, nspname, relname, relpages) AS ("
2040 "\nSELECT c.oid, r.nspname, c.relname, c.relpages "
2042 "\nINNER JOIN pg_catalog.pg_index i "
2043 "ON r.oid = i.indrelid "
2044 "INNER JOIN pg_catalog.pg_class c "
2045 "ON i.indexrelid = c.oid "
2046 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP));
2049 "\nINNER JOIN pg_catalog.pg_namespace n "
2050 "ON c.relnamespace = n.oid"
2051 "\nLEFT OUTER JOIN exclude_pat ep "
2052 "ON (n.nspname ~ ep.nsp_regex OR ep.nsp_regex IS NULL) "
2053 "AND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL) "
2055 "\nWHERE ep.pattern_id IS NULL");
2060 " AND c.relam = %u "
2065 " AND c.relnamespace != %u",
2066 PG_TOAST_NAMESPACE);
2078 ", toast_index (oid, nspname, relname, relpages) AS ("
2079 "\nSELECT c.oid, 'pg_toast', c.relname, c.relpages "
2081 "INNER JOIN pg_catalog.pg_index i "
2082 "ON t.oid = i.indrelid"
2083 "\nINNER JOIN pg_catalog.pg_class c "
2084 "ON i.indexrelid = c.oid "
2085 "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP));
2088 "\nLEFT OUTER JOIN exclude_pat ep "
2089 "ON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL) "
2090 "AND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL) "
2091 "AND ep.btree_only "
2092 "WHERE ep.pattern_id IS NULL");
2111 "\nSELECT pattern_id, is_heap, is_btree, oid, nspname, relname, relpages "
2115 "\nSELECT pattern_id, is_heap, is_btree, "
2116 "NULL::OID AS oid, "
2117 "NULL::TEXT AS nspname, "
2118 "NULL::TEXT AS relname, "
2119 "NULL::INTEGER AS relpages"
2121 "WHERE pattern_id IS NOT NULL "
2124 "\nSELECT NULL::INTEGER AS pattern_id, "
2125 "is_heap, is_btree, oid, nspname, relname, relpages "
2131 "\nSELECT NULL::INTEGER AS pattern_id, TRUE AS is_heap, "
2132 "FALSE AS is_btree, oid, nspname, relname, relpages "
2138 "\nSELECT NULL::INTEGER AS pattern_id, FALSE AS is_heap, "
2139 "TRUE AS is_btree, oid, nspname, relname, relpages "
2145 "\nSELECT NULL::INTEGER AS pattern_id, FALSE AS is_heap, "
2146 "TRUE AS is_btree, oid, nspname, relname, relpages "
2147 "FROM toast_index");
2149 "\n) AS combined_records "
2150 "ORDER BY relpages DESC NULLS FIRST, oid");
2163 for (
i = 0;
i < ntups;
i++)
2165 int pattern_id = -1;
2166 bool is_heap =
false;
2169 const char *nspname = NULL;
2188 if (pattern_id >= 0)
2196 pg_fatal(
"internal error: received unexpected relation pattern_id %d",
2208 Assert((is_heap && !is_btree) || (is_btree && !is_heap));
Datum now(PG_FUNCTION_ARGS)
#define PG_USED_FOR_ASSERTS_ONLY
#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)
PGconn * connectDatabase(const ConnParams *cparams, const char *progname, bool echo, bool fail_ok, bool allow_password_reuse)
PGresult * executeQuery(PGconn *conn, const char *query)
#define fprintf(file, fmt, msg)
char * PQdb(const PGconn *conn)
PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
char * PQerrorMessage(const PGconn *conn)
void PQfreemem(void *ptr)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
ExecStatusType PQresultStatus(const PGresult *res)
void PQclear(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
Assert(PointerIsAligned(start, uint64))
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 void executeCommand(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)