agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v50 1/7] sequential scan for dshash 6+ messages / 3 participants [nested] [flat]
* [PATCH v50 1/7] sequential scan for dshash @ 2020-03-13 07:58 Kyotaro Horiguchi <[email protected]> 0 siblings, 0 replies; 6+ messages in thread From: Kyotaro Horiguchi @ 2020-03-13 07:58 UTC (permalink / raw) Dshash did not allow scan the all entries sequentially. This adds the functionality. The interface is similar but a bit different both from that of dynahash and simple dshash search functions. One of the most significant differences is the sequential scan interface of dshash always needs a call to dshash_seq_term when scan ends. Another is locking. Dshash holds partition lock when returning an entry, dshash_seq_next() also holds lock when returning an entry but callers shouldn't release it, since the lock is essential to continue a scan. The seqscan interface allows entry deletion while a scan. The in-scan deletion should be performed by dshash_delete_current(). --- src/backend/lib/dshash.c | 160 ++++++++++++++++++++++++++++++- src/include/lib/dshash.h | 22 +++++ src/tools/pgindent/typedefs.list | 1 + 3 files changed, 182 insertions(+), 1 deletion(-) diff --git a/src/backend/lib/dshash.c b/src/backend/lib/dshash.c index e0c763be32..520bfa0979 100644 --- a/src/backend/lib/dshash.c +++ b/src/backend/lib/dshash.c @@ -127,6 +127,10 @@ struct dshash_table #define NUM_SPLITS(size_log2) \ (size_log2 - DSHASH_NUM_PARTITIONS_LOG2) +/* How many buckets are there in a given size? */ +#define NUM_BUCKETS(size_log2) \ + (((size_t) 1) << (size_log2)) + /* How many buckets are there in each partition at a given size? */ #define BUCKETS_PER_PARTITION(size_log2) \ (((size_t) 1) << NUM_SPLITS(size_log2)) @@ -153,6 +157,10 @@ struct dshash_table #define BUCKET_INDEX_FOR_PARTITION(partition, size_log2) \ ((partition) << NUM_SPLITS(size_log2)) +/* Choose partition based on bucket index. */ +#define PARTITION_FOR_BUCKET_INDEX(bucket_idx, size_log2) \ + ((bucket_idx) >> NUM_SPLITS(size_log2)) + /* The head of the active bucket for a given hash value (lvalue). */ #define BUCKET_FOR_HASH(hash_table, hash) \ (hash_table->buckets[ \ @@ -324,7 +332,7 @@ dshash_destroy(dshash_table *hash_table) ensure_valid_bucket_pointers(hash_table); /* Free all the entries. */ - size = ((size_t) 1) << hash_table->size_log2; + size = NUM_BUCKETS(hash_table->size_log2); for (i = 0; i < size; ++i) { dsa_pointer item_pointer = hash_table->buckets[i]; @@ -592,6 +600,156 @@ dshash_memhash(const void *v, size_t size, void *arg) return tag_hash(v, size); } +/* + * dshash_seq_init/_next/_term + * Sequentially scan through dshash table and return all the + * elements one by one, return NULL when no more. + * + * dshash_seq_term should always be called when a scan finished. + * The caller may delete returned elements midst of a scan by using + * dshash_delete_current(). exclusive must be true to delete elements. + */ +void +dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, + bool exclusive) +{ + status->hash_table = hash_table; + status->curbucket = 0; + status->nbuckets = 0; + status->curitem = NULL; + status->pnextitem = InvalidDsaPointer; + status->curpartition = -1; + status->exclusive = exclusive; +} + +/* + * Returns the next element. + * + * Returned elements are locked and the caller must not explicitly release + * it. It is released at the next call to dshash_next(). + */ +void * +dshash_seq_next(dshash_seq_status *status) +{ + dsa_pointer next_item_pointer; + + if (status->curitem == NULL) + { + int partition; + + Assert(status->curbucket == 0); + Assert(!status->hash_table->find_locked); + + /* first shot. grab the first item. */ + partition = + PARTITION_FOR_BUCKET_INDEX(status->curbucket, + status->hash_table->size_log2); + LWLockAcquire(PARTITION_LOCK(status->hash_table, partition), + status->exclusive ? LW_EXCLUSIVE : LW_SHARED); + status->curpartition = partition; + + /* resize doesn't happen from now until seq scan ends */ + status->nbuckets = + NUM_BUCKETS(status->hash_table->control->size_log2); + ensure_valid_bucket_pointers(status->hash_table); + + next_item_pointer = status->hash_table->buckets[status->curbucket]; + } + else + next_item_pointer = status->pnextitem; + + Assert(LWLockHeldByMeInMode(PARTITION_LOCK(status->hash_table, + status->curpartition), + status->exclusive ? LW_EXCLUSIVE : LW_SHARED)); + + /* Move to the next bucket if we finished the current bucket */ + while (!DsaPointerIsValid(next_item_pointer)) + { + int next_partition; + + if (++status->curbucket >= status->nbuckets) + { + /* all buckets have been scanned. finish. */ + return NULL; + } + + /* Check if move to the next partition */ + next_partition = + PARTITION_FOR_BUCKET_INDEX(status->curbucket, + status->hash_table->size_log2); + + if (status->curpartition != next_partition) + { + /* + * Move to the next partition. Lock the next partition then release + * the current, not in the reverse order to avoid concurrent + * resizing. Avoid dead lock by taking lock in the same order + * with resize(). + */ + LWLockAcquire(PARTITION_LOCK(status->hash_table, + next_partition), + status->exclusive ? LW_EXCLUSIVE : LW_SHARED); + LWLockRelease(PARTITION_LOCK(status->hash_table, + status->curpartition)); + status->curpartition = next_partition; + } + + next_item_pointer = status->hash_table->buckets[status->curbucket]; + } + + status->curitem = + dsa_get_address(status->hash_table->area, next_item_pointer); + status->hash_table->find_locked = true; + status->hash_table->find_exclusively_locked = status->exclusive; + + /* + * The caller may delete the item. Store the next item in case of deletion. + */ + status->pnextitem = status->curitem->next; + + return ENTRY_FROM_ITEM(status->curitem); +} + +/* + * Terminates the seqscan and release all locks. + * + * Should be always called when finishing or exiting a seqscan. + */ +void +dshash_seq_term(dshash_seq_status *status) +{ + status->hash_table->find_locked = false; + status->hash_table->find_exclusively_locked = false; + + if (status->curpartition >= 0) + LWLockRelease(PARTITION_LOCK(status->hash_table, status->curpartition)); +} + +/* Remove the current entry while a seq scan. */ +void +dshash_delete_current(dshash_seq_status *status) +{ + dshash_table *hash_table = status->hash_table; + dshash_table_item *item = status->curitem; + size_t partition = PARTITION_FOR_HASH(item->hash); + + Assert(status->exclusive); + Assert(hash_table->control->magic == DSHASH_MAGIC); + Assert(hash_table->find_locked); + Assert(hash_table->find_exclusively_locked); + Assert(LWLockHeldByMeInMode(PARTITION_LOCK(hash_table, partition), + LW_EXCLUSIVE)); + + delete_item(hash_table, item); +} + +/* Get the current entry while a seq scan. */ +void * +dshash_get_current(dshash_seq_status *status) +{ + return ENTRY_FROM_ITEM(status->curitem); +} + /* * Print debugging information about the internal state of the hash table to * stderr. The caller must hold no partition locks. diff --git a/src/include/lib/dshash.h b/src/include/lib/dshash.h index c069ec9de7..a6ea377173 100644 --- a/src/include/lib/dshash.h +++ b/src/include/lib/dshash.h @@ -59,6 +59,21 @@ typedef struct dshash_parameters struct dshash_table_item; typedef struct dshash_table_item dshash_table_item; +/* + * Sequential scan state. The detail is exposed to let users know the storage + * size but it should be considered as an opaque type by callers. + */ +typedef struct dshash_seq_status +{ + dshash_table *hash_table; /* dshash table working on */ + int curbucket; /* bucket number we are at */ + int nbuckets; /* total number of buckets in the dshash */ + dshash_table_item *curitem; /* item we are currently at */ + dsa_pointer pnextitem; /* dsa-pointer to the next item */ + int curpartition; /* partition number we are at */ + bool exclusive; /* locking mode */ +} dshash_seq_status; + /* Creating, sharing and destroying from hash tables. */ extern dshash_table *dshash_create(dsa_area *area, const dshash_parameters *params, @@ -80,6 +95,13 @@ extern bool dshash_delete_key(dshash_table *hash_table, const void *key); extern void dshash_delete_entry(dshash_table *hash_table, void *entry); extern void dshash_release_lock(dshash_table *hash_table, void *entry); +/* seq scan support */ +extern void dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, + bool exclusive); +extern void *dshash_seq_next(dshash_seq_status *status); +extern void dshash_seq_term(dshash_seq_status *status); +extern void dshash_delete_current(dshash_seq_status *status); +extern void *dshash_get_current(dshash_seq_status *status); /* Convenience hash and compare functions wrapping memcmp and tag_hash. */ extern int dshash_memcmp(const void *a, const void *b, size_t size, void *arg); extern dshash_hash dshash_memhash(const void *v, size_t size, void *arg); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 8bd95aefa1..2b591e94e6 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2954,6 +2954,7 @@ dshash_hash dshash_hash_function dshash_parameters dshash_partition +dshash_seq_status dshash_table dshash_table_control dshash_table_handle -- 2.27.0 ----Next_Part(Tue_Mar__9_18_29_34_2021_806)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="v50-0002-Add-conditional-lock-feature-to-dshash.patch" ^ permalink raw reply [nested|flat] 6+ messages in thread
* [PATCH v2 1/1] Fix the memory leak in psql describe @ 2022-07-19 10:27 Japin Li <[email protected]> 0 siblings, 0 replies; 6+ messages in thread From: Japin Li @ 2022-07-19 10:27 UTC (permalink / raw) --- src/bin/psql/describe.c | 168 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 0ce38e4b4c..7a070a6cd0 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -112,7 +112,10 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -182,7 +185,10 @@ describeAccessMethods(const char *pattern, bool verbose) NULL, "amname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -244,7 +250,10 @@ describeTablespaces(const char *pattern, bool verbose) NULL, "spcname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -534,7 +543,10 @@ describeFunctions(const char *functypes, const char *func_pattern, "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } for (int i = 0; i < num_arg_patterns; i++) { @@ -561,7 +573,10 @@ describeFunctions(const char *functypes, const char *func_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } } else { @@ -682,7 +697,10 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -836,7 +854,10 @@ describeOperators(const char *oper_pattern, "n.nspname", "o.oprname", NULL, "pg_catalog.pg_operator_is_visible(o.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } if (num_arg_patterns == 1) appendPQExpBufferStr(&buf, " AND o.oprleft = 0\n"); @@ -866,7 +887,10 @@ describeOperators(const char *oper_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } } else { @@ -953,7 +977,10 @@ listAllDbs(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "d.datname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); res = PSQLexec(buf.data); @@ -1106,7 +1133,10 @@ permissionsList(const char *pattern) "n.nspname", "c.relname", NULL, "n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -1177,7 +1207,10 @@ listDefaultACLs(const char *pattern) "pg_catalog.pg_get_userbyid(d.defaclrole)", NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;"); @@ -1253,7 +1286,10 @@ objectDescription(const char *pattern, bool showSystem) false, "n.nspname", "pgc.conname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } /* Domain constraint descriptions */ appendPQExpBuffer(&buf, @@ -1277,7 +1313,10 @@ objectDescription(const char *pattern, bool showSystem) false, "n.nspname", "pgc.conname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } /* Operator class descriptions */ appendPQExpBuffer(&buf, @@ -1301,7 +1340,10 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "o.opcname", NULL, "pg_catalog.pg_opclass_is_visible(o.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } /* Operator family descriptions */ appendPQExpBuffer(&buf, @@ -1325,7 +1367,10 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "opf.opfname", NULL, "pg_catalog.pg_opfamily_is_visible(opf.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } /* Rule descriptions (ignore rules for views) */ appendPQExpBuffer(&buf, @@ -1348,7 +1393,10 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "r.rulename", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } /* Trigger descriptions */ appendPQExpBuffer(&buf, @@ -1370,7 +1418,10 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "t.tgname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, ") AS tt\n" @@ -1428,7 +1479,10 @@ describeTableDetails(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2, 3;"); @@ -3614,7 +3668,10 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -3739,11 +3796,17 @@ listDbRoleSettings(const char *pattern, const char *pattern2) gettext_noop("Settings")); if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, &havewhere, 1)) + { + termPQExpBuffer(&buf); return false; + } if (!validateSQLNamePattern(&buf, pattern2, havewhere, false, NULL, "d.datname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); res = PSQLexec(buf.data); @@ -3940,7 +4003,10 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1,2;"); @@ -4157,7 +4223,10 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";", mixed_output ? "\"Type\" DESC, " : "", @@ -4233,7 +4302,10 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "l.lanname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } if (!showSystem && !pattern) appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n"); @@ -4319,7 +4391,10 @@ listDomains(const char *pattern, bool verbose, bool showSystem) "n.nspname", "t.typname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4395,7 +4470,10 @@ listConversions(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.conname", NULL, "pg_catalog.pg_conversion_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4542,7 +4620,10 @@ listEventTriggers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "evtname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1"); @@ -4638,7 +4719,10 @@ listExtendedStats(const char *pattern) "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname", NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4742,7 +4826,10 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(ts.oid, NULL)", "pg_catalog.pg_type_is_visible(ts.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, ") OR (true"); @@ -4751,7 +4838,10 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(tt.oid, NULL)", "pg_catalog.pg_type_is_visible(tt.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;"); @@ -4851,7 +4941,10 @@ listCollations(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.collname", NULL, "pg_catalog.pg_collation_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4914,7 +5007,10 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) NULL, "n.nspname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5029,7 +5125,10 @@ listTSParsers(const char *pattern, bool verbose) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5072,7 +5171,10 @@ listTSParsersVerbose(const char *pattern) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5215,7 +5317,10 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) res = PSQLexec(buf.data); termPQExpBuffer(&buf); if (!res) + { + termPQExpBuffer(&title); return false; + } myopt.nullPrint = NULL; if (nspname) @@ -5281,7 +5386,10 @@ listTSDictionaries(const char *pattern, bool verbose) "n.nspname", "d.dictname", NULL, "pg_catalog.pg_ts_dict_is_visible(d.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5344,7 +5452,10 @@ listTSTemplates(const char *pattern, bool verbose) "n.nspname", "t.tmplname", NULL, "pg_catalog.pg_ts_template_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5396,7 +5507,10 @@ listTSConfigs(const char *pattern, bool verbose) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5440,7 +5554,10 @@ listTSConfigsVerbose(const char *pattern) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 3, 2;"); @@ -5613,7 +5730,10 @@ listForeignDataWrappers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "fdwname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5687,7 +5807,10 @@ listForeignServers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "s.srvname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5740,7 +5863,10 @@ listUserMappings(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "um.srvname", "um.usename", NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5810,7 +5936,10 @@ listForeignTables(const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5859,7 +5988,10 @@ listExtensions(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5900,7 +6032,10 @@ listExtensionContents(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6093,7 +6228,10 @@ listPublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6208,7 +6346,10 @@ describePublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2;"); @@ -6420,7 +6561,10 @@ describeSubscriptions(const char *pattern, bool verbose) NULL, "subname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6524,7 +6668,10 @@ listOperatorClasses(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (type_pattern) { /* Match type name pattern against either internal or external name */ @@ -6533,7 +6680,10 @@ listOperatorClasses(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -6600,7 +6750,10 @@ listOperatorFamilies(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (type_pattern) { appendPQExpBuffer(&buf, @@ -6617,7 +6770,10 @@ listOperatorFamilies(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, " )\n"); } @@ -6699,13 +6855,19 @@ listOpFamilyOperators(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "nsf.nspname", "of.opfname", NULL, NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " o.amoplefttype = o.amoprighttype DESC,\n" @@ -6787,12 +6949,18 @@ listOpFamilyFunctions(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "ns.nspname", "of.opfname", NULL, NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " ap.amproclefttype = ap.amprocrighttype DESC,\n" -- 2.17.1 --=-=-=-- ^ permalink raw reply [nested|flat] 6+ messages in thread
* [PATCH v1 1/1] Fix the memory leak in psql describe @ 2022-07-19 10:27 Japin Li <[email protected]> 0 siblings, 0 replies; 6+ messages in thread From: Japin Li @ 2022-07-19 10:27 UTC (permalink / raw) --- src/bin/psql/describe.c | 150 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 0ce38e4b4c..11a441f52f 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -112,7 +112,10 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -182,7 +185,10 @@ describeAccessMethods(const char *pattern, bool verbose) NULL, "amname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -244,7 +250,10 @@ describeTablespaces(const char *pattern, bool verbose) NULL, "spcname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -534,7 +543,10 @@ describeFunctions(const char *functypes, const char *func_pattern, "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } for (int i = 0; i < num_arg_patterns; i++) { @@ -561,7 +573,10 @@ describeFunctions(const char *functypes, const char *func_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } } else { @@ -682,7 +697,10 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -836,7 +854,10 @@ describeOperators(const char *oper_pattern, "n.nspname", "o.oprname", NULL, "pg_catalog.pg_operator_is_visible(o.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } if (num_arg_patterns == 1) appendPQExpBufferStr(&buf, " AND o.oprleft = 0\n"); @@ -866,7 +887,10 @@ describeOperators(const char *oper_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } } else { @@ -953,7 +977,10 @@ listAllDbs(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "d.datname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); res = PSQLexec(buf.data); @@ -1106,7 +1133,10 @@ permissionsList(const char *pattern) "n.nspname", "c.relname", NULL, "n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -1177,7 +1207,10 @@ listDefaultACLs(const char *pattern) "pg_catalog.pg_get_userbyid(d.defaclrole)", NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;"); @@ -1428,7 +1461,10 @@ describeTableDetails(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2, 3;"); @@ -3614,7 +3650,10 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -3739,11 +3778,17 @@ listDbRoleSettings(const char *pattern, const char *pattern2) gettext_noop("Settings")); if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, &havewhere, 1)) + { + termPQExpBuffer(&buf); return false; + } if (!validateSQLNamePattern(&buf, pattern2, havewhere, false, NULL, "d.datname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); res = PSQLexec(buf.data); @@ -3940,7 +3985,10 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1,2;"); @@ -4157,7 +4205,10 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";", mixed_output ? "\"Type\" DESC, " : "", @@ -4233,7 +4284,10 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "l.lanname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } if (!showSystem && !pattern) appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n"); @@ -4319,7 +4373,10 @@ listDomains(const char *pattern, bool verbose, bool showSystem) "n.nspname", "t.typname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4395,7 +4452,10 @@ listConversions(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.conname", NULL, "pg_catalog.pg_conversion_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4542,7 +4602,10 @@ listEventTriggers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "evtname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1"); @@ -4638,7 +4701,10 @@ listExtendedStats(const char *pattern) "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname", NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4742,7 +4808,10 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(ts.oid, NULL)", "pg_catalog.pg_type_is_visible(ts.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, ") OR (true"); @@ -4751,7 +4820,10 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(tt.oid, NULL)", "pg_catalog.pg_type_is_visible(tt.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;"); @@ -4851,7 +4923,10 @@ listCollations(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.collname", NULL, "pg_catalog.pg_collation_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4914,7 +4989,10 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) NULL, "n.nspname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5029,7 +5107,10 @@ listTSParsers(const char *pattern, bool verbose) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5072,7 +5153,10 @@ listTSParsersVerbose(const char *pattern) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5215,7 +5299,10 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) res = PSQLexec(buf.data); termPQExpBuffer(&buf); if (!res) + { + termPQExpBuffer(&title); return false; + } myopt.nullPrint = NULL; if (nspname) @@ -5281,7 +5368,10 @@ listTSDictionaries(const char *pattern, bool verbose) "n.nspname", "d.dictname", NULL, "pg_catalog.pg_ts_dict_is_visible(d.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5344,7 +5434,10 @@ listTSTemplates(const char *pattern, bool verbose) "n.nspname", "t.tmplname", NULL, "pg_catalog.pg_ts_template_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5396,7 +5489,10 @@ listTSConfigs(const char *pattern, bool verbose) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5440,7 +5536,10 @@ listTSConfigsVerbose(const char *pattern) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 3, 2;"); @@ -5613,7 +5712,10 @@ listForeignDataWrappers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "fdwname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5687,7 +5789,10 @@ listForeignServers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "s.srvname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5740,7 +5845,10 @@ listUserMappings(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "um.srvname", "um.usename", NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5810,7 +5918,10 @@ listForeignTables(const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5859,7 +5970,10 @@ listExtensions(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5900,7 +6014,10 @@ listExtensionContents(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6093,7 +6210,10 @@ listPublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6208,7 +6328,10 @@ describePublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2;"); @@ -6420,7 +6543,10 @@ describeSubscriptions(const char *pattern, bool verbose) NULL, "subname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6524,7 +6650,10 @@ listOperatorClasses(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (type_pattern) { /* Match type name pattern against either internal or external name */ @@ -6533,7 +6662,10 @@ listOperatorClasses(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -6600,7 +6732,10 @@ listOperatorFamilies(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (type_pattern) { appendPQExpBuffer(&buf, @@ -6617,7 +6752,10 @@ listOperatorFamilies(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, " )\n"); } @@ -6699,13 +6837,19 @@ listOpFamilyOperators(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "nsf.nspname", "of.opfname", NULL, NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " o.amoplefttype = o.amoprighttype DESC,\n" @@ -6787,12 +6931,18 @@ listOpFamilyFunctions(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) + { + termPQExpBuffer(&buf); return false; + } if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "ns.nspname", "of.opfname", NULL, NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " ap.amproclefttype = ap.amprocrighttype DESC,\n" -- 2.17.1 --=-=-=-- ^ permalink raw reply [nested|flat] 6+ messages in thread
* [PATCH v5] fix the memory leak in psql describe @ 2022-07-20 03:47 Michael Paquier <[email protected]> 0 siblings, 0 replies; 6+ messages in thread From: Michael Paquier @ 2022-07-20 03:47 UTC (permalink / raw) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 88d92a08ae..77b0f87e39 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -112,7 +112,10 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -182,7 +185,10 @@ describeAccessMethods(const char *pattern, bool verbose) NULL, "amname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -244,7 +250,10 @@ describeTablespaces(const char *pattern, bool verbose) NULL, "spcname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -534,7 +543,7 @@ describeFunctions(const char *functypes, const char *func_pattern, "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) - return false; + goto error_return; for (int i = 0; i < num_arg_patterns; i++) { @@ -561,7 +570,7 @@ describeFunctions(const char *functypes, const char *func_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) - return false; + goto error_return; } else { @@ -599,6 +608,10 @@ describeFunctions(const char *functypes, const char *func_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -682,7 +695,10 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -836,7 +852,7 @@ describeOperators(const char *oper_pattern, "n.nspname", "o.oprname", NULL, "pg_catalog.pg_operator_is_visible(o.oid)", NULL, 3)) - return false; + goto error_return; if (num_arg_patterns == 1) appendPQExpBufferStr(&buf, " AND o.oprleft = 0\n"); @@ -866,7 +882,7 @@ describeOperators(const char *oper_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) - return false; + goto error_return; } else { @@ -890,6 +906,10 @@ describeOperators(const char *oper_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -953,7 +973,10 @@ listAllDbs(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "d.datname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); res = PSQLexec(buf.data); @@ -1106,7 +1129,10 @@ permissionsList(const char *pattern) "n.nspname", "c.relname", NULL, "n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -1177,16 +1203,13 @@ listDefaultACLs(const char *pattern) "pg_catalog.pg_get_userbyid(d.defaclrole)", NULL, NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;"); res = PSQLexec(buf.data); if (!res) - { - termPQExpBuffer(&buf); - return false; - } + goto error_return; myopt.nullPrint = NULL; printfPQExpBuffer(&buf, _("Default access privileges")); @@ -1200,6 +1223,10 @@ listDefaultACLs(const char *pattern) termPQExpBuffer(&buf); PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -1253,7 +1280,7 @@ objectDescription(const char *pattern, bool showSystem) false, "n.nspname", "pgc.conname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) - return false; + goto error_return; /* Domain constraint descriptions */ appendPQExpBuffer(&buf, @@ -1277,7 +1304,7 @@ objectDescription(const char *pattern, bool showSystem) false, "n.nspname", "pgc.conname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) - return false; + goto error_return; /* Operator class descriptions */ appendPQExpBuffer(&buf, @@ -1301,7 +1328,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "o.opcname", NULL, "pg_catalog.pg_opclass_is_visible(o.oid)", NULL, 3)) - return false; + goto error_return; /* Operator family descriptions */ appendPQExpBuffer(&buf, @@ -1325,7 +1352,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "opf.opfname", NULL, "pg_catalog.pg_opfamily_is_visible(opf.oid)", NULL, 3)) - return false; + goto error_return; /* Rule descriptions (ignore rules for views) */ appendPQExpBuffer(&buf, @@ -1348,7 +1375,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "r.rulename", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) - return false; + goto error_return; /* Trigger descriptions */ appendPQExpBuffer(&buf, @@ -1370,7 +1397,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "t.tgname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, ") AS tt\n" @@ -1393,6 +1420,10 @@ objectDescription(const char *pattern, bool showSystem) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -1428,7 +1459,10 @@ describeTableDetails(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2, 3;"); @@ -3614,7 +3648,10 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -3739,11 +3776,11 @@ listDbRoleSettings(const char *pattern, const char *pattern2) gettext_noop("Settings")); if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, &havewhere, 1)) - return false; + goto error_return; if (!validateSQLNamePattern(&buf, pattern2, havewhere, false, NULL, "d.datname", NULL, NULL, NULL, 1)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); res = PSQLexec(buf.data); @@ -3779,6 +3816,10 @@ listDbRoleSettings(const char *pattern, const char *pattern2) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -3940,7 +3981,10 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1,2;"); @@ -4157,7 +4201,10 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";", mixed_output ? "\"Type\" DESC, " : "", @@ -4233,7 +4280,10 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "l.lanname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } if (!showSystem && !pattern) appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n"); @@ -4319,7 +4369,10 @@ listDomains(const char *pattern, bool verbose, bool showSystem) "n.nspname", "t.typname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4395,7 +4448,10 @@ listConversions(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.conname", NULL, "pg_catalog.pg_conversion_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4542,7 +4598,10 @@ listEventTriggers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "evtname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1"); @@ -4638,7 +4697,10 @@ listExtendedStats(const char *pattern) "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname", NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4742,7 +4804,7 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(ts.oid, NULL)", "pg_catalog.pg_type_is_visible(ts.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, ") OR (true"); @@ -4751,7 +4813,7 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(tt.oid, NULL)", "pg_catalog.pg_type_is_visible(tt.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;"); @@ -4770,6 +4832,10 @@ listCasts(const char *pattern, bool verbose) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -4851,7 +4917,10 @@ listCollations(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.collname", NULL, "pg_catalog.pg_collation_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4914,7 +4983,10 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) NULL, "n.nspname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5029,7 +5101,10 @@ listTSParsers(const char *pattern, bool verbose) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5072,7 +5147,10 @@ listTSParsersVerbose(const char *pattern) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5215,7 +5293,10 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) res = PSQLexec(buf.data); termPQExpBuffer(&buf); if (!res) + { + termPQExpBuffer(&title); return false; + } myopt.nullPrint = NULL; if (nspname) @@ -5281,7 +5362,10 @@ listTSDictionaries(const char *pattern, bool verbose) "n.nspname", "d.dictname", NULL, "pg_catalog.pg_ts_dict_is_visible(d.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5344,7 +5428,10 @@ listTSTemplates(const char *pattern, bool verbose) "n.nspname", "t.tmplname", NULL, "pg_catalog.pg_ts_template_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5396,7 +5483,10 @@ listTSConfigs(const char *pattern, bool verbose) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5440,7 +5530,10 @@ listTSConfigsVerbose(const char *pattern) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 3, 2;"); @@ -5613,7 +5706,10 @@ listForeignDataWrappers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "fdwname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5687,7 +5783,10 @@ listForeignServers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "s.srvname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5740,7 +5839,10 @@ listUserMappings(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "um.srvname", "um.usename", NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5810,7 +5912,10 @@ listForeignTables(const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5859,7 +5964,10 @@ listExtensions(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5900,7 +6008,10 @@ listExtensionContents(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6014,8 +6125,7 @@ validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where, { pg_log_error("improper qualified name (too many dotted names): %s", pattern); - termPQExpBuffer(&dbbuf); - return false; + goto error_return; } if (maxparts > 1 && dotcnt == maxparts - 1) @@ -6023,16 +6133,21 @@ validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where, if (PQdb(pset.db) == NULL) { pg_log_error("You are currently not connected to a database."); - return false; + goto error_return; } if (strcmp(PQdb(pset.db), dbbuf.data) != 0) { pg_log_error("cross-database references are not implemented: %s", pattern); - return false; + goto error_return; } } + termPQExpBuffer(&dbbuf); return true; + +error_return: + termPQExpBuffer(&dbbuf); + return false; } /* @@ -6090,7 +6205,10 @@ listPublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6205,7 +6323,10 @@ describePublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2;"); @@ -6417,7 +6538,10 @@ describeSubscriptions(const char *pattern, bool verbose) NULL, "subname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6521,7 +6645,7 @@ listOperatorClasses(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (type_pattern) { /* Match type name pattern against either internal or external name */ @@ -6530,7 +6654,7 @@ listOperatorClasses(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) - return false; + goto error_return; } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -6549,6 +6673,10 @@ listOperatorClasses(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -6597,7 +6725,7 @@ listOperatorFamilies(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (type_pattern) { appendPQExpBuffer(&buf, @@ -6614,7 +6742,7 @@ listOperatorFamilies(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, " )\n"); } @@ -6634,6 +6762,10 @@ listOperatorFamilies(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -6696,13 +6828,13 @@ listOpFamilyOperators(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "nsf.nspname", "of.opfname", NULL, NULL, NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " o.amoplefttype = o.amoprighttype DESC,\n" @@ -6725,6 +6857,10 @@ listOpFamilyOperators(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -6784,12 +6920,12 @@ listOpFamilyFunctions(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "ns.nspname", "of.opfname", NULL, NULL, NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " ap.amproclefttype = ap.amprocrighttype DESC,\n" @@ -6810,6 +6946,10 @@ listOpFamilyFunctions(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* -- 2.33.0.windows.2 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=pg14-v5-0001-fix-the-memory-leak-in-psql-describe.patch ^ permalink raw reply [nested|flat] 6+ messages in thread
* [PATCH v5 1/1] fix the memory leak in psql describe @ 2022-07-20 06:12 Japin Li <[email protected]> 0 siblings, 0 replies; 6+ messages in thread From: Japin Li @ 2022-07-20 06:12 UTC (permalink / raw) --- src/bin/psql/describe.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index c7ff55fbd7..32a18becba 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3441,7 +3441,10 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) res = PSQLexec(buf.data); if (!res) + { + termPQExpBuffer(&buf); return false; + } nrows = PQntuples(res); attr = pg_malloc0((nrows + 1) * sizeof(*attr)); @@ -4800,7 +4803,10 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) res = PSQLexec(buf.data); termPQExpBuffer(&buf); if (!res) + { + termPQExpBuffer(&title); return false; + } myopt.nullPrint = NULL; if (nspname) -- 2.17.1 --=-=-=-- ^ permalink raw reply [nested|flat] 6+ messages in thread
* [PATCH v5 1/1] fix the memory leak in psql describe @ 2022-07-20 07:52 Japin Li <[email protected]> 0 siblings, 0 replies; 6+ messages in thread From: Japin Li @ 2022-07-20 07:52 UTC (permalink / raw) --- src/bin/psql/describe.c | 201 ++++++++++++++++++++++++++++++++++------ 1 file changed, 172 insertions(+), 29 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 8fe39475fa..c6ff5a9d14 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -131,7 +131,10 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -201,7 +204,10 @@ describeAccessMethods(const char *pattern, bool verbose) NULL, "amname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -290,7 +296,10 @@ describeTablespaces(const char *pattern, bool verbose) NULL, "spcname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -656,7 +665,7 @@ describeFunctions(const char *functypes, const char *func_pattern, "n.nspname", "p.proname", NULL, "pg_catalog.pg_function_is_visible(p.oid)", NULL, 3)) - return false; + goto error_return; for (int i = 0; i < num_arg_patterns; i++) { @@ -683,7 +692,7 @@ describeFunctions(const char *functypes, const char *func_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) - return false; + goto error_return; } else { @@ -721,6 +730,10 @@ describeFunctions(const char *functypes, const char *func_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -827,7 +840,10 @@ describeTypes(const char *pattern, bool verbose, bool showSystem) "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -982,7 +998,7 @@ describeOperators(const char *oper_pattern, "n.nspname", "o.oprname", NULL, "pg_catalog.pg_operator_is_visible(o.oid)", NULL, 3)) - return false; + goto error_return; if (num_arg_patterns == 1) appendPQExpBufferStr(&buf, " AND o.oprleft = 0\n"); @@ -1012,7 +1028,7 @@ describeOperators(const char *oper_pattern, true, false, nspname, typname, ft, tiv, NULL, 3)) - return false; + goto error_return; } else { @@ -1036,6 +1052,10 @@ describeOperators(const char *oper_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -1093,7 +1113,10 @@ listAllDbs(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "d.datname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); res = PSQLexec(buf.data); @@ -1247,7 +1270,10 @@ permissionsList(const char *pattern) "n.nspname", "c.relname", NULL, "n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -1328,7 +1354,10 @@ listDefaultACLs(const char *pattern) "pg_catalog.pg_get_userbyid(d.defaclrole)", NULL, NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;"); @@ -1404,7 +1433,7 @@ objectDescription(const char *pattern, bool showSystem) false, "n.nspname", "pgc.conname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) - return false; + goto error_return; /* Domain constraint descriptions */ appendPQExpBuffer(&buf, @@ -1428,7 +1457,7 @@ objectDescription(const char *pattern, bool showSystem) false, "n.nspname", "pgc.conname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) - return false; + goto error_return; /* @@ -1458,7 +1487,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "o.opcname", NULL, "pg_catalog.pg_opclass_is_visible(o.oid)", NULL, 3)) - return false; + goto error_return; } /* @@ -1489,7 +1518,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "opf.opfname", NULL, "pg_catalog.pg_opfamily_is_visible(opf.oid)", NULL, 3)) - return false; + goto error_return; } /* Rule descriptions (ignore rules for views) */ @@ -1513,7 +1542,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "r.rulename", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) - return false; + goto error_return; /* Trigger descriptions */ appendPQExpBuffer(&buf, @@ -1535,7 +1564,7 @@ objectDescription(const char *pattern, bool showSystem) "n.nspname", "t.tgname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, ") AS tt\n" @@ -1558,6 +1587,10 @@ objectDescription(const char *pattern, bool showSystem) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -1593,7 +1626,10 @@ describeTableDetails(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2, 3;"); @@ -3852,7 +3888,7 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, NULL, 1)) - return false; + goto error_return; } else { @@ -3869,14 +3905,14 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "u.usename", NULL, NULL, NULL, 1)) - return false; + goto error_return; } appendPQExpBufferStr(&buf, "ORDER BY 1;"); res = PSQLexec(buf.data); if (!res) - return false; + goto error_return; nrows = PQntuples(res); attr = pg_malloc0((nrows + 1) * sizeof(*attr)); @@ -3962,6 +3998,10 @@ describeRoles(const char *pattern, bool verbose, bool showSystem) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } static void @@ -4006,11 +4046,11 @@ listDbRoleSettings(const char *pattern, const char *pattern2) gettext_noop("Settings")); if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "r.rolname", NULL, NULL, &havewhere, 1)) - return false; + goto error_return; if (!validateSQLNamePattern(&buf, pattern2, havewhere, false, NULL, "d.datname", NULL, NULL, NULL, 1)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); res = PSQLexec(buf.data); @@ -4046,6 +4086,10 @@ listDbRoleSettings(const char *pattern, const char *pattern2) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } @@ -4229,7 +4273,10 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1,2;"); @@ -4446,7 +4493,10 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";", mixed_output ? "\"Type\" DESC, " : "", @@ -4527,7 +4577,10 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "l.lanname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } if (!showSystem && !pattern) appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n"); @@ -4620,7 +4673,10 @@ listDomains(const char *pattern, bool verbose, bool showSystem) "n.nspname", "t.typname", NULL, "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4696,7 +4752,10 @@ listConversions(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.conname", NULL, "pg_catalog.pg_conversion_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4764,7 +4823,10 @@ listEventTriggers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "evtname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1"); @@ -4860,7 +4922,10 @@ listExtendedStats(const char *pattern) "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname", NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -4971,7 +5036,7 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(ts.oid, NULL)", "pg_catalog.pg_type_is_visible(ts.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, ") OR (true"); @@ -4980,7 +5045,7 @@ listCasts(const char *pattern, bool verbose) "pg_catalog.format_type(tt.oid, NULL)", "pg_catalog.pg_type_is_visible(tt.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;"); @@ -4999,6 +5064,10 @@ listCasts(const char *pattern, bool verbose) PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -5081,7 +5150,10 @@ listCollations(const char *pattern, bool verbose, bool showSystem) "n.nspname", "c.collname", NULL, "pg_catalog.pg_collation_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5142,7 +5214,10 @@ listSchemas(const char *pattern, bool verbose, bool showSystem) NULL, "n.nspname", NULL, NULL, NULL, 2)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5204,7 +5279,10 @@ listTSParsers(const char *pattern, bool verbose) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5247,7 +5325,10 @@ listTSParsersVerbose(const char *pattern) "n.nspname", "p.prsname", NULL, "pg_catalog.pg_ts_parser_is_visible(p.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5390,7 +5471,10 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) res = PSQLexec(buf.data); termPQExpBuffer(&buf); if (!res) + { + termPQExpBuffer(&title); return false; + } myopt.nullPrint = NULL; if (nspname) @@ -5466,7 +5550,10 @@ listTSDictionaries(const char *pattern, bool verbose) "n.nspname", "d.dictname", NULL, "pg_catalog.pg_ts_dict_is_visible(d.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5539,7 +5626,10 @@ listTSTemplates(const char *pattern, bool verbose) "n.nspname", "t.tmplname", NULL, "pg_catalog.pg_ts_template_is_visible(t.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5601,7 +5691,10 @@ listTSConfigs(const char *pattern, bool verbose) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -5645,7 +5738,10 @@ listTSConfigsVerbose(const char *pattern) "n.nspname", "c.cfgname", NULL, "pg_catalog.pg_ts_config_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 3, 2;"); @@ -5834,7 +5930,10 @@ listForeignDataWrappers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "fdwname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5918,7 +6017,10 @@ listForeignServers(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "s.srvname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -5981,7 +6083,10 @@ listUserMappings(const char *pattern, bool verbose) if (!validateSQLNamePattern(&buf, pattern, false, false, NULL, "um.srvname", "um.usename", NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -6061,7 +6166,10 @@ listForeignTables(const char *pattern, bool verbose) "n.nspname", "c.relname", NULL, "pg_catalog.pg_table_is_visible(c.oid)", NULL, 3)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); @@ -6120,7 +6228,10 @@ listExtensions(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6171,7 +6282,10 @@ listExtensionContents(const char *pattern) NULL, "e.extname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6285,8 +6399,7 @@ validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where, { pg_log_error("improper qualified name (too many dotted names): %s", pattern); - termPQExpBuffer(&dbbuf); - return false; + goto error_return; } if (maxparts > 1 && dotcnt == maxparts-1) @@ -6294,16 +6407,21 @@ validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where, if (PQdb(pset.db) == NULL) { pg_log_error("You are currently not connected to a database."); - return false; + goto error_return; } if (strcmp(PQdb(pset.db), dbbuf.data) != 0) { pg_log_error("cross-database references are not implemented: %s", pattern); - return false; + goto error_return; } } + termPQExpBuffer(&dbbuf); return true; + +error_return: + termPQExpBuffer(&dbbuf); + return false; } /* @@ -6361,7 +6479,10 @@ listPublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6430,7 +6551,10 @@ describePublications(const char *pattern) NULL, "pubname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 2;"); @@ -6616,7 +6740,10 @@ describeSubscriptions(const char *pattern, bool verbose) NULL, "subname", NULL, NULL, NULL, 1)) + { + termPQExpBuffer(&buf); return false; + } appendPQExpBufferStr(&buf, "ORDER BY 1;"); @@ -6725,7 +6852,7 @@ listOperatorClasses(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (type_pattern) { /* Match type name pattern against either internal or external name */ @@ -6734,7 +6861,7 @@ listOperatorClasses(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) - return false; + goto error_return; } appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); @@ -6753,6 +6880,10 @@ listOperatorClasses(const char *access_method_pattern, PQclear(res); return true; + + error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -6801,7 +6932,7 @@ listOperatorFamilies(const char *access_method_pattern, if (!validateSQLNamePattern(&buf, access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (type_pattern) { appendPQExpBuffer(&buf, @@ -6818,7 +6949,7 @@ listOperatorFamilies(const char *access_method_pattern, "pg_catalog.format_type(t.oid, NULL)", "pg_catalog.pg_type_is_visible(t.oid)", NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, " )\n"); } @@ -6838,6 +6969,10 @@ listOperatorFamilies(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -6900,13 +7035,13 @@ listOpFamilyOperators(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "nsf.nspname", "of.opfname", NULL, NULL, NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " o.amoplefttype = o.amoprighttype DESC,\n" @@ -6929,6 +7064,10 @@ listOpFamilyOperators(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } /* @@ -6988,12 +7127,12 @@ listOpFamilyFunctions(const char *access_method_pattern, false, false, NULL, "am.amname", NULL, NULL, &have_where, 1)) - return false; + goto error_return; if (family_pattern) if (!validateSQLNamePattern(&buf, family_pattern, have_where, false, "ns.nspname", "of.opfname", NULL, NULL, NULL, 3)) - return false; + goto error_return; appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n" " ap.amproclefttype = ap.amprocrighttype DESC,\n" @@ -7014,4 +7153,8 @@ listOpFamilyFunctions(const char *access_method_pattern, PQclear(res); return true; + +error_return: + termPQExpBuffer(&buf); + return false; } -- 2.17.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=pg10-11-12-v5-0001-fix-the-memory-leak-in-psql-describe.patch ^ permalink raw reply [nested|flat] 6+ messages in thread
end of thread, other threads:[~2022-07-20 07:52 UTC | newest] Thread overview: 6+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-03-13 07:58 [PATCH v50 1/7] sequential scan for dshash Kyotaro Horiguchi <[email protected]> 2022-07-19 10:27 [PATCH v1 1/1] Fix the memory leak in psql describe Japin Li <[email protected]> 2022-07-19 10:27 [PATCH v2 1/1] Fix the memory leak in psql describe Japin Li <[email protected]> 2022-07-20 03:47 [PATCH v5] fix the memory leak in psql describe Michael Paquier <[email protected]> 2022-07-20 06:12 [PATCH v5 1/1] fix the memory leak in psql describe Japin Li <[email protected]> 2022-07-20 07:52 [PATCH v5 1/1] fix the memory leak in psql describe Japin Li <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox