18 #include "catalog/pg_am_d.h"
19 #include "catalog/pg_namespace_d.h"
116 .strict_names =
true,
117 .show_progress =
false,
119 .install_missing =
false,
120 .install_schema =
"pg_catalog",
121 .include = {NULL, 0},
122 .exclude = {NULL, 0},
127 .no_toast_expansion =
false,
128 .reconcile_toast =
true,
129 .on_error_stop =
false,
133 .parent_check =
false,
134 .rootdescend =
false,
135 .heapallindexed =
false,
136 .checkunique =
false,
137 .no_btree_expansion =
false
173 "SELECT n.nspname, x.extversion FROM pg_catalog.pg_extension x"
174 "\nJOIN pg_catalog.pg_namespace n ON x.extnamespace = n.oid"
175 "\nWHERE x.extname = 'amcheck'";
186 static void progress_report(uint64 relations_total, uint64 relations_checked,
187 uint64 relpages_total, uint64 relpages_checked,
188 const char *
datname,
bool force,
bool finished);
201 const char *initial_dbname);
206 #define log_no_match(...) do { \
207 if (opts.strict_names) \
208 pg_log_error(__VA_ARGS__); \
210 pg_log_warning(__VA_ARGS__); \
213 #define FREE_AND_SET_NULL(x) do { \
226 const char *latest_datname;
227 int parallel_workers;
231 uint64 pageschecked = 0;
232 uint64 pagestotal = 0;
233 uint64 relprogress = 0;
236 static struct option long_options[] = {
281 const char *db = NULL;
282 const char *maintenance_db = NULL;
284 const char *host = NULL;
285 const char *
port = NULL;
298 while ((
c =
getopt_long(argc, argv,
"ad:D:eh:Hi:I:j:p:Pr:R:s:S:t:T:U:vwW",
299 long_options, &optindex)) != -1)
302 unsigned long optval;
403 pg_fatal(
"invalid argument for option %s",
"--skip");
407 optval = strtoul(
optarg, &endptr, 10);
408 if (endptr ==
optarg || *endptr !=
'\0' || errno != 0)
411 pg_fatal(
"start block out of bounds");
416 optval = strtoul(
optarg, &endptr, 10);
417 if (endptr ==
optarg || *endptr !=
'\0' || errno != 0)
420 pg_fatal(
"end block out of bounds");
452 pg_fatal(
"end block precedes start block");
466 pg_log_error(
"too many command-line arguments (first is \"%s\")",
486 pg_fatal(
"cannot specify a database name with --all");
487 cparams.
dbname = maintenance_db;
492 pg_fatal(
"cannot specify both a database name and database patterns");
503 if (cparams.
dbname == NULL)
505 if (getenv(
"PGDATABASE"))
506 cparams.
dbname = getenv(
"PGDATABASE");
507 else if (getenv(
"PGUSER"))
508 cparams.
dbname = getenv(
"PGUSER");
516 if (databases.
head == NULL)
527 for (cell = databases.
head; cell; cell = cell->
next)
531 const char *amcheck_schema = NULL;
557 install_sql =
psprintf(
"CREATE EXTENSION IF NOT EXISTS amcheck WITH SCHEMA %s",
587 pg_log_warning(
"skipping database \"%s\": amcheck is not installed",
595 pg_log_info(
"in database \"%s\": using amcheck version \"%s\" in schema \"%s\"",
598 strlen(amcheck_schema));
615 const char *amcheck_version =
PQgetvalue(result, 0, 1);
617 sscanf(amcheck_version,
"%d.%d.%d", &vmaj, &vmin, &vrev);
622 if ((vmaj == 1 && vmin < 4) || vmaj == 0)
624 pg_log_warning(
"option %s is not supported by amcheck version %s",
625 "--checkunique", amcheck_version);
653 log_no_match(
"no btree indexes to check matching \"%s\"",
656 log_no_match(
"no relations to check in schemas matching \"%s\"",
675 parallel_workers = 0;
676 for (cell = relations.
head; cell; cell = cell->
next)
700 latest_datname = NULL;
710 for (relprogress = 0, cell = relations.
head; cell; cell = cell->
next)
732 latest_datname,
false,
false);
809 progress_report(reltotal, relprogress, pagestotal, pageschecked, NULL,
true,
true);
845 "SELECT v.blkno, v.offnum, v.attnum, v.msg "
846 "FROM pg_catalog.pg_class c, %s.verify_heapam("
847 "\nrelation := c.oid, on_error_stop := %s, check_toast := %s, skip := '%s'",
859 "\n) v WHERE c.oid = %u "
860 "AND c.relpersistence != 't'",
887 "SELECT %s.bt_index_parent_check("
888 "index := c.oid, heapallindexed := %s, rootdescend := %s "
890 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
892 "AND c.oid = i.indexrelid "
893 "AND c.relpersistence != 't' "
894 "AND i.indisready AND i.indisvalid AND i.indislive",
902 "SELECT %s.bt_index_check("
903 "index := c.oid, heapallindexed := %s "
905 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
907 "AND c.oid = i.indexrelid "
908 "AND c.relpersistence != 't' "
909 "AND i.indisready AND i.indisvalid AND i.indislive",
937 pg_log_error(
"error sending command to database \"%s\": %s",
964 const char *severity;
977 if (severity == NULL)
979 if (strcmp(severity,
"FATAL") == 0)
981 if (strcmp(severity,
"PANIC") == 0)
1017 if (
c[0] ==
'\n' &&
c[1] !=
'\0')
1049 for (
i = 0;
i < ntups;
i++)
1060 printf(
_(
"heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n"),
1067 printf(
_(
"heap table \"%s.%s.%s\", block %s, offset %s:\n"),
1073 printf(
_(
"heap table \"%s.%s.%s\", block %s:\n"),
1078 printf(
_(
"heap table \"%s.%s.%s\":\n"),
1089 printf(
_(
"heap table \"%s.%s.%s\":\n"),
1144 pg_log_warning(
"btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d",
1158 printf(
_(
"btree index \"%s.%s.%s\":\n"),
1183 printf(
_(
"%s checks objects in a PostgreSQL database for corruption.\n\n"),
progname);
1186 printf(
_(
"\nTarget options:\n"));
1187 printf(
_(
" -a, --all check all databases\n"));
1188 printf(
_(
" -d, --database=PATTERN check matching database(s)\n"));
1189 printf(
_(
" -D, --exclude-database=PATTERN do NOT check matching database(s)\n"));
1190 printf(
_(
" -i, --index=PATTERN check matching index(es)\n"));
1191 printf(
_(
" -I, --exclude-index=PATTERN do NOT check matching index(es)\n"));
1192 printf(
_(
" -r, --relation=PATTERN check matching relation(s)\n"));
1193 printf(
_(
" -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n"));
1194 printf(
_(
" -s, --schema=PATTERN check matching schema(s)\n"));
1195 printf(
_(
" -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n"));
1196 printf(
_(
" -t, --table=PATTERN check matching table(s)\n"));
1197 printf(
_(
" -T, --exclude-table=PATTERN do NOT check matching table(s)\n"));
1198 printf(
_(
" --no-dependent-indexes do NOT expand list of relations to include indexes\n"));
1199 printf(
_(
" --no-dependent-toast do NOT expand list of relations to include TOAST tables\n"));
1200 printf(
_(
" --no-strict-names do NOT require patterns to match objects\n"));
1201 printf(
_(
"\nTable checking options:\n"));
1202 printf(
_(
" --exclude-toast-pointers do NOT follow relation TOAST pointers\n"));
1203 printf(
_(
" --on-error-stop stop checking at end of first corrupt page\n"));
1204 printf(
_(
" --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n"));
1205 printf(
_(
" --startblock=BLOCK begin checking table(s) at the given block number\n"));
1206 printf(
_(
" --endblock=BLOCK check table(s) only up to the given block number\n"));
1207 printf(
_(
"\nB-tree index checking options:\n"));
1208 printf(
_(
" --checkunique check unique constraint if index is unique\n"));
1209 printf(
_(
" --heapallindexed check that all heap tuples are found within indexes\n"));
1210 printf(
_(
" --parent-check check index parent/child relationships\n"));
1211 printf(
_(
" --rootdescend search from root page to refind tuples\n"));
1212 printf(
_(
"\nConnection options:\n"));
1213 printf(
_(
" -h, --host=HOSTNAME database server host or socket directory\n"));
1214 printf(
_(
" -p, --port=PORT database server port\n"));
1215 printf(
_(
" -U, --username=USERNAME user name to connect as\n"));
1216 printf(
_(
" -w, --no-password never prompt for password\n"));
1217 printf(
_(
" -W, --password force password prompt\n"));
1218 printf(
_(
" --maintenance-db=DBNAME alternate maintenance database\n"));
1219 printf(
_(
"\nOther options:\n"));
1220 printf(
_(
" -e, --echo show the commands being sent to the server\n"));
1221 printf(
_(
" -j, --jobs=NUM use this many concurrent connections to the server\n"));
1222 printf(
_(
" -P, --progress show progress information\n"));
1223 printf(
_(
" -v, --verbose write a lot of output\n"));
1224 printf(
_(
" -V, --version output version information, then exit\n"));
1225 printf(
_(
" --install-missing install missing extensions\n"));
1226 printf(
_(
" -?, --help show this help, then exit\n"));
1228 printf(
_(
"\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
1229 printf(
_(
"%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
1243 uint64 relpages_total, uint64 relpages_checked,
1244 const char *
datname,
bool force,
bool finished)
1246 int percent_rel = 0;
1247 int percent_pages = 0;
1248 char checked_rel[32];
1250 char checked_pages[32];
1251 char total_pages[32];
1262 if (relations_total)
1263 percent_rel = (int) (relations_checked * 100 / relations_total);
1265 percent_pages = (int) (relpages_checked * 100 / relpages_total);
1272 #define VERBOSE_DATNAME_LENGTH 35
1282 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s"),
1283 (
int) strlen(total_rel),
1284 checked_rel, total_rel, percent_rel,
1285 (
int) strlen(total_pages),
1286 checked_pages, total_pages, percent_pages,
1293 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)"),
1294 (
int) strlen(total_rel),
1295 checked_rel, total_rel, percent_rel,
1296 (
int) strlen(total_pages),
1297 checked_pages, total_pages, percent_pages,
1299 truncate ?
"..." :
"",
1308 _(
"%*s/%s relations (%d%%), %*s/%s pages (%d%%)"),
1309 (
int) strlen(total_rel),
1310 checked_rel, total_rel, percent_rel,
1311 (
int) strlen(total_pages),
1312 checked_pages, total_pages, percent_pages);
1318 if (!finished && isatty(fileno(stderr)))
1320 fputc(
'\r', stderr);
1324 fputc(
'\n', stderr);
1340 result = &pia->
data[pia->
len - 1];
1341 memset(result, 0,
sizeof(*result));
1367 pg_log_error(
"improper qualified name (too many dotted names): %s", pattern);
1400 pg_log_error(
"improper qualified name (too many dotted names): %s", pattern);
1429 int encoding,
bool heap_only,
bool btree_only)
1445 pg_log_error(
"improper relation name (too many dotted names): %s", pattern);
1545 have_values =
false;
1546 for (pattern_id = 0; pattern_id < pia->
len; pattern_id++)
1584 const char *initial_dbname)
1598 pg_log_info(
"including database \"%s\"", initial_dbname);
1634 "\ndatabase (datname) AS ("
1635 "\nSELECT d.datname "
1636 "FROM pg_catalog.pg_database d "
1637 "LEFT OUTER JOIN exclude_raw e "
1638 "ON d.datname ~ e.rgx "
1639 "\nWHERE d.datallowconn AND datconnlimit != -2 "
1640 "AND e.pattern_id IS NULL"
1649 "\ninclude_pat (pattern_id, checkable) AS ("
1650 "\nSELECT i.pattern_id, "
1652 "WHERE d IS NOT NULL"
1654 "\nFROM include_raw i "
1655 "LEFT OUTER JOIN database d "
1656 "ON d.datname ~ i.rgx"
1657 "\nGROUP BY i.pattern_id"
1667 "\nfiltered_databases (datname) AS ("
1668 "\nSELECT DISTINCT d.datname "
1672 " INNER JOIN include_raw i "
1673 "ON d.datname ~ i.rgx");
1680 "\nSELECT pattern_id, datname FROM ("
1681 "\nSELECT pattern_id, NULL::TEXT AS datname "
1683 "WHERE checkable = 0 "
1685 "\nSELECT NULL, datname "
1686 "FROM filtered_databases"
1687 ") AS combined_records"
1688 "\nORDER BY pattern_id NULLS LAST, datname");
1701 for (fatal =
false,
i = 0;
i < ntups;
i++)
1703 int pattern_id = -1;
1711 if (pattern_id >= 0)
1719 pg_fatal(
"internal error: received unexpected database pattern_id %d",
1721 log_no_match(
"no connectable databases to check matching \"%s\"",
1732 if (initial_dbname != NULL && strcmp(initial_dbname,
datname) == 0)
1783 have_values =
false;
1784 for (pattern_id = 0; pattern_id < pia->
len; pattern_id++)
1820 "\nSELECT NULL::INTEGER, NULL::TEXT, NULL::TEXT, "
1821 "NULL::TEXT, NULL::BOOLEAN, NULL::BOOLEAN "
1848 "\n%s (pattern_id, nsp_regex, rel_regex, heap_only, btree_only) AS ("
1849 "\nSELECT pattern_id, nsp_regex, rel_regex, heap_only, btree_only "
1851 "\nWHERE (r.db_regex IS NULL "
1857 " AND (r.nsp_regex IS NOT NULL"
1858 " OR r.rel_regex IS NOT NULL)"
1899 " include_raw (pattern_id, db_regex, nsp_regex, rel_regex, heap_only, btree_only) AS (");
1909 " exclude_raw (pattern_id, db_regex, nsp_regex, rel_regex, heap_only, btree_only) AS (");
1917 " relation (pattern_id, oid, nspname, relname, reltoastrelid, relpages, is_heap, is_btree) AS ("
1918 "\nSELECT DISTINCT ON (c.oid");
1924 "\nc.oid, n.nspname, c.relname, c.reltoastrelid, c.relpages, "
1925 "c.relam = %u AS is_heap, "
1926 "c.relam = %u AS is_btree"
1927 "\nFROM pg_catalog.pg_class c "
1928 "INNER JOIN pg_catalog.pg_namespace n "
1929 "ON c.relnamespace = n.oid",
1930 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1933 "\nINNER JOIN include_pat ip"
1934 "\nON (n.nspname ~ ip.nsp_regex OR ip.nsp_regex IS NULL)"
1935 "\nAND (c.relname ~ ip.rel_regex OR ip.rel_regex IS NULL)"
1936 "\nAND (c.relam = %u OR NOT ip.heap_only)"
1937 "\nAND (c.relam = %u OR NOT ip.btree_only)",
1938 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1941 "\nLEFT OUTER JOIN exclude_pat ep"
1942 "\nON (n.nspname ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
1943 "\nAND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
1944 "\nAND (c.relam = %u OR NOT ep.heap_only OR ep.rel_regex IS NULL)"
1945 "\nAND (c.relam = %u OR NOT ep.btree_only OR ep.rel_regex IS NULL)",
1946 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1974 " AND c.relam = %u "
1975 "AND c.relkind IN ('r', 'S', 'm', 't') "
1976 "AND c.relnamespace != %u",
1977 HEAP_TABLE_AM_OID, PG_TOAST_NAMESPACE);
1980 " AND c.relam IN (%u, %u)"
1981 "AND c.relkind IN ('r', 'S', 'm', 't', 'i') "
1982 "AND ((c.relam = %u AND c.relkind IN ('r', 'S', 'm', 't')) OR "
1983 "(c.relam = %u AND c.relkind = 'i'))",
1984 HEAP_TABLE_AM_OID, BTREE_AM_OID,
1985 HEAP_TABLE_AM_OID, BTREE_AM_OID);
1988 "\nORDER BY c.oid)");
1998 ", toast (oid, nspname, relname, relpages) AS ("
1999 "\nSELECT t.oid, 'pg_toast', t.relname, t.relpages"
2000 "\nFROM pg_catalog.pg_class t "
2001 "INNER JOIN relation r "
2002 "ON r.reltoastrelid = t.oid");
2005 "\nLEFT OUTER JOIN exclude_pat ep"
2006 "\nON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
2007 "\nAND (t.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
2008 "\nAND ep.heap_only"
2009 "\nWHERE ep.pattern_id IS NULL"
2010 "\nAND t.relpersistence != 't'");
2022 ", index (oid, nspname, relname, relpages) AS ("
2023 "\nSELECT c.oid, r.nspname, c.relname, c.relpages "
2025 "\nINNER JOIN pg_catalog.pg_index i "
2026 "ON r.oid = i.indrelid "
2027 "INNER JOIN pg_catalog.pg_class c "
2028 "ON i.indexrelid = c.oid "
2029 "AND c.relpersistence != 't'");
2032 "\nINNER JOIN pg_catalog.pg_namespace n "
2033 "ON c.relnamespace = n.oid"
2034 "\nLEFT OUTER JOIN exclude_pat ep "
2035 "ON (n.nspname ~ ep.nsp_regex OR ep.nsp_regex IS NULL) "
2036 "AND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL) "
2038 "\nWHERE ep.pattern_id IS NULL");
2043 " AND c.relam = %u "
2044 "AND c.relkind = 'i'",
2048 " AND c.relnamespace != %u",
2049 PG_TOAST_NAMESPACE);
2061 ", toast_index (oid, nspname, relname, relpages) AS ("
2062 "\nSELECT c.oid, 'pg_toast', c.relname, c.relpages "
2064 "INNER JOIN pg_catalog.pg_index i "
2065 "ON t.oid = i.indrelid"
2066 "\nINNER JOIN pg_catalog.pg_class c "
2067 "ON i.indexrelid = c.oid "
2068 "AND c.relpersistence != 't'");
2071 "\nLEFT OUTER JOIN exclude_pat ep "
2072 "ON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL) "
2073 "AND (c.relname ~ ep.rel_regex OR ep.rel_regex IS NULL) "
2074 "AND ep.btree_only "
2075 "WHERE ep.pattern_id IS NULL");
2081 " AND c.relkind = 'i')",
2094 "\nSELECT pattern_id, is_heap, is_btree, oid, nspname, relname, relpages "
2098 "\nSELECT pattern_id, is_heap, is_btree, "
2099 "NULL::OID AS oid, "
2100 "NULL::TEXT AS nspname, "
2101 "NULL::TEXT AS relname, "
2102 "NULL::INTEGER AS relpages"
2104 "WHERE pattern_id IS NOT NULL "
2107 "\nSELECT NULL::INTEGER AS pattern_id, "
2108 "is_heap, is_btree, oid, nspname, relname, relpages "
2114 "\nSELECT NULL::INTEGER AS pattern_id, TRUE AS is_heap, "
2115 "FALSE AS is_btree, oid, nspname, relname, relpages "
2121 "\nSELECT NULL::INTEGER AS pattern_id, FALSE AS is_heap, "
2122 "TRUE AS is_btree, oid, nspname, relname, relpages "
2128 "\nSELECT NULL::INTEGER AS pattern_id, FALSE AS is_heap, "
2129 "TRUE AS is_btree, oid, nspname, relname, relpages "
2130 "FROM toast_index");
2132 "\n) AS combined_records "
2133 "ORDER BY relpages DESC NULLS FIRST, oid");
2146 for (
i = 0;
i < ntups;
i++)
2148 int pattern_id = -1;
2149 bool is_heap =
false;
2152 const char *nspname = NULL;
2171 if (pattern_id >= 0)
2179 pg_fatal(
"internal error: received unexpected relation pattern_id %d",
2191 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)
static void PGresult * res
char * PQdb(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
ExecStatusType PQresultStatus(const PGresult *res)
int PQntuples(const PGresult *res)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
int PQsendQuery(PGconn *conn, const char *query)
char * PQresultErrorField(const PGresult *res, int fieldcode)
void * pg_realloc(void *ptr, size_t size)
void * pg_malloc0(size_t size)
char * pg_strdup(const char *in)
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)
ParallelSlot * ParallelSlotsGetIdle(ParallelSlotArray *sa, const char *dbname)
bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa)
ParallelSlotArray * ParallelSlotsSetup(int numslots, ConnParams *cparams, const char *progname, bool echo, const char *initcmd)
void ParallelSlotsTerminate(ParallelSlotArray *sa)
void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn)
static void ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler, void *context)
#define VERBOSE_DATNAME_LENGTH
static char * indent_lines(const char *str)
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 PatternInfo * extend_pattern_info_array(PatternInfoArray *pia)
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 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 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)