@@ -122,6 +122,18 @@ const char *const SeqTypeNames[] =
122
122
StaticAssertDecl(lengthof(SeqTypeNames) == (SEQTYPE_BIGINT + 1),
123
123
"array length mismatch");
124
124
125
+ typedef struct
126
+ {
127
+ Oid oid; /* sequence OID */
128
+ SeqType seqtype; /* data type of sequence */
129
+ bool cycled; /* whether sequence cycles */
130
+ int64 minv; /* minimum value */
131
+ int64 maxv; /* maximum value */
132
+ int64 startv; /* start value */
133
+ int64 incby; /* increment value */
134
+ int64 cache; /* cache size */
135
+ } SequenceItem;
136
+
125
137
typedef enum OidOptions
126
138
{
127
139
zeroIsError = 1,
@@ -191,6 +203,10 @@ static int nseclabels = 0;
191
203
static BinaryUpgradeClassOidItem *binaryUpgradeClassOids = NULL;
192
204
static int nbinaryUpgradeClassOids = 0;
193
205
206
+ /* sorted table of sequences */
207
+ static SequenceItem *sequences = NULL;
208
+ static int nsequences = 0;
209
+
194
210
/*
195
211
* The default number of rows per INSERT when
196
212
* --inserts is specified without --rows-per-insert
@@ -288,6 +304,7 @@ static void dumpTable(Archive *fout, const TableInfo *tbinfo);
288
304
static void dumpTableSchema(Archive *fout, const TableInfo *tbinfo);
289
305
static void dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo);
290
306
static void dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo);
307
+ static void collectSequences(Archive *fout);
291
308
static void dumpSequence(Archive *fout, const TableInfo *tbinfo);
292
309
static void dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo);
293
310
static void dumpIndex(Archive *fout, const IndxInfo *indxinfo);
@@ -1010,6 +1027,9 @@ main(int argc, char **argv)
1010
1027
if (dopt.binary_upgrade)
1011
1028
collectBinaryUpgradeClassOids(fout);
1012
1029
1030
+ /* Collect sequence information. */
1031
+ collectSequences(fout);
1032
+
1013
1033
/* Lastly, create dummy objects to represent the section boundaries */
1014
1034
boundaryObjs = createBoundaryObjects();
1015
1035
@@ -17282,6 +17302,65 @@ parse_sequence_type(const char *name)
17282
17302
return (SeqType) 0; /* keep compiler quiet */
17283
17303
}
17284
17304
17305
+ /*
17306
+ * bsearch() comparator for SequenceItem
17307
+ */
17308
+ static int
17309
+ SequenceItemCmp(const void *p1, const void *p2)
17310
+ {
17311
+ SequenceItem v1 = *((const SequenceItem *) p1);
17312
+ SequenceItem v2 = *((const SequenceItem *) p2);
17313
+
17314
+ return pg_cmp_u32(v1.oid, v2.oid);
17315
+ }
17316
+
17317
+ /*
17318
+ * collectSequences
17319
+ *
17320
+ * Construct a table of sequence information. This table is sorted by OID for
17321
+ * speed in lookup.
17322
+ */
17323
+ static void
17324
+ collectSequences(Archive *fout)
17325
+ {
17326
+ PGresult *res;
17327
+ const char *query;
17328
+
17329
+ /*
17330
+ * Before Postgres 10, sequence metadata is in the sequence itself. With
17331
+ * some extra effort, we might be able to use the sorted table for those
17332
+ * versions, but for now it seems unlikely to be worth it.
17333
+ */
17334
+ if (fout->remoteVersion < 100000)
17335
+ return;
17336
+ else
17337
+ query = "SELECT seqrelid, format_type(seqtypid, NULL), "
17338
+ "seqstart, seqincrement, "
17339
+ "seqmax, seqmin, "
17340
+ "seqcache, seqcycle "
17341
+ "FROM pg_catalog.pg_sequence "
17342
+ "ORDER BY seqrelid";
17343
+
17344
+ res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
17345
+
17346
+ nsequences = PQntuples(res);
17347
+ sequences = (SequenceItem *) pg_malloc(nsequences * sizeof(SequenceItem));
17348
+
17349
+ for (int i = 0; i < nsequences; i++)
17350
+ {
17351
+ sequences[i].oid = atooid(PQgetvalue(res, i, 0));
17352
+ sequences[i].seqtype = parse_sequence_type(PQgetvalue(res, i, 1));
17353
+ sequences[i].startv = strtoi64(PQgetvalue(res, i, 2), NULL, 10);
17354
+ sequences[i].incby = strtoi64(PQgetvalue(res, i, 3), NULL, 10);
17355
+ sequences[i].maxv = strtoi64(PQgetvalue(res, i, 4), NULL, 10);
17356
+ sequences[i].minv = strtoi64(PQgetvalue(res, i, 5), NULL, 10);
17357
+ sequences[i].cache = strtoi64(PQgetvalue(res, i, 6), NULL, 10);
17358
+ sequences[i].cycled = (strcmp(PQgetvalue(res, i, 7), "t") == 0);
17359
+ }
17360
+
17361
+ PQclear(res);
17362
+ }
17363
+
17285
17364
/*
17286
17365
* dumpSequence
17287
17366
* write the declaration (not data) of one user-defined sequence
@@ -17290,37 +17369,36 @@ static void
17290
17369
dumpSequence(Archive *fout, const TableInfo *tbinfo)
17291
17370
{
17292
17371
DumpOptions *dopt = fout->dopt;
17293
- PGresult *res;
17294
- SeqType seqtype;
17295
- bool cycled;
17372
+ SequenceItem *seq;
17296
17373
bool is_ascending;
17297
17374
int64 default_minv,
17298
- default_maxv,
17299
- minv,
17300
- maxv,
17301
- startv,
17302
- incby,
17303
- cache;
17375
+ default_maxv;
17304
17376
PQExpBuffer query = createPQExpBuffer();
17305
17377
PQExpBuffer delqry = createPQExpBuffer();
17306
17378
char *qseqname;
17307
17379
TableInfo *owning_tab = NULL;
17308
17380
17309
17381
qseqname = pg_strdup(fmtId(tbinfo->dobj.name));
17310
17382
17383
+ /*
17384
+ * For versions >= 10, the sequence information is gathered in a sorted
17385
+ * table before any calls to dumpSequence(). See collectSequences() for
17386
+ * more information.
17387
+ */
17311
17388
if (fout->remoteVersion >= 100000)
17312
17389
{
17313
- appendPQExpBuffer(query,
17314
- "SELECT format_type(seqtypid, NULL), "
17315
- "seqstart, seqincrement, "
17316
- "seqmax, seqmin, "
17317
- "seqcache, seqcycle "
17318
- "FROM pg_catalog.pg_sequence "
17319
- "WHERE seqrelid = '%u'::oid",
17320
- tbinfo->dobj.catId.oid);
17390
+ SequenceItem key = {0};
17391
+
17392
+ Assert(sequences);
17393
+
17394
+ key.oid = tbinfo->dobj.catId.oid;
17395
+ seq = bsearch(&key, sequences, nsequences,
17396
+ sizeof(SequenceItem), SequenceItemCmp);
17321
17397
}
17322
17398
else
17323
17399
{
17400
+ PGresult *res;
17401
+
17324
17402
/*
17325
17403
* Before PostgreSQL 10, sequence metadata is in the sequence itself.
17326
17404
*
@@ -17332,46 +17410,47 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo)
17332
17410
"start_value, increment_by, max_value, min_value, "
17333
17411
"cache_value, is_cycled FROM %s",
17334
17412
fmtQualifiedDumpable(tbinfo));
17335
- }
17336
-
17337
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
17338
17413
17339
- if (PQntuples(res) != 1)
17340
- pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
17341
- "query to get data of sequence \"%s\" returned %d rows (expected 1)",
17342
- PQntuples(res)),
17343
- tbinfo->dobj.name, PQntuples(res));
17414
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
17344
17415
17345
- seqtype = parse_sequence_type(PQgetvalue(res, 0, 0));
17346
- startv = strtoi64(PQgetvalue(res, 0, 1), NULL, 10);
17347
- incby = strtoi64(PQgetvalue(res, 0, 2), NULL, 10);
17348
- maxv = strtoi64(PQgetvalue(res, 0, 3), NULL, 10);
17349
- minv = strtoi64(PQgetvalue(res, 0, 4), NULL, 10);
17350
- cache = strtoi64(PQgetvalue(res, 0, 5), NULL, 10);
17351
- cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
17416
+ if (PQntuples(res) != 1)
17417
+ pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
17418
+ "query to get data of sequence \"%s\" returned %d rows (expected 1)",
17419
+ PQntuples(res)),
17420
+ tbinfo->dobj.name, PQntuples(res));
17421
+
17422
+ seq = pg_malloc0(sizeof(SequenceItem));
17423
+ seq->seqtype = parse_sequence_type(PQgetvalue(res, 0, 0));
17424
+ seq->startv = strtoi64(PQgetvalue(res, 0, 1), NULL, 10);
17425
+ seq->incby = strtoi64(PQgetvalue(res, 0, 2), NULL, 10);
17426
+ seq->maxv = strtoi64(PQgetvalue(res, 0, 3), NULL, 10);
17427
+ seq->minv = strtoi64(PQgetvalue(res, 0, 4), NULL, 10);
17428
+ seq->cache = strtoi64(PQgetvalue(res, 0, 5), NULL, 10);
17429
+ seq->cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
17352
17430
17353
- PQclear(res);
17431
+ PQclear(res);
17432
+ }
17354
17433
17355
17434
/* Calculate default limits for a sequence of this type */
17356
- is_ascending = (incby >= 0);
17357
- if (seqtype == SEQTYPE_SMALLINT)
17435
+ is_ascending = (seq-> incby >= 0);
17436
+ if (seq-> seqtype == SEQTYPE_SMALLINT)
17358
17437
{
17359
17438
default_minv = is_ascending ? 1 : PG_INT16_MIN;
17360
17439
default_maxv = is_ascending ? PG_INT16_MAX : -1;
17361
17440
}
17362
- else if (seqtype == SEQTYPE_INTEGER)
17441
+ else if (seq-> seqtype == SEQTYPE_INTEGER)
17363
17442
{
17364
17443
default_minv = is_ascending ? 1 : PG_INT32_MIN;
17365
17444
default_maxv = is_ascending ? PG_INT32_MAX : -1;
17366
17445
}
17367
- else if (seqtype == SEQTYPE_BIGINT)
17446
+ else if (seq-> seqtype == SEQTYPE_BIGINT)
17368
17447
{
17369
17448
default_minv = is_ascending ? 1 : PG_INT64_MIN;
17370
17449
default_maxv = is_ascending ? PG_INT64_MAX : -1;
17371
17450
}
17372
17451
else
17373
17452
{
17374
- pg_fatal("unrecognized sequence type: %d", seqtype);
17453
+ pg_fatal("unrecognized sequence type: %d", seq-> seqtype);
17375
17454
default_minv = default_maxv = 0; /* keep compiler quiet */
17376
17455
}
17377
17456
@@ -17422,27 +17501,27 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo)
17422
17501
"UNLOGGED " : "",
17423
17502
fmtQualifiedDumpable(tbinfo));
17424
17503
17425
- if (seqtype != SEQTYPE_BIGINT)
17426
- appendPQExpBuffer(query, " AS %s\n", SeqTypeNames[seqtype]);
17504
+ if (seq-> seqtype != SEQTYPE_BIGINT)
17505
+ appendPQExpBuffer(query, " AS %s\n", SeqTypeNames[seq-> seqtype]);
17427
17506
}
17428
17507
17429
- appendPQExpBuffer(query, " START WITH " INT64_FORMAT "\n", startv);
17508
+ appendPQExpBuffer(query, " START WITH " INT64_FORMAT "\n", seq-> startv);
17430
17509
17431
- appendPQExpBuffer(query, " INCREMENT BY " INT64_FORMAT "\n", incby);
17510
+ appendPQExpBuffer(query, " INCREMENT BY " INT64_FORMAT "\n", seq-> incby);
17432
17511
17433
- if (minv != default_minv)
17434
- appendPQExpBuffer(query, " MINVALUE " INT64_FORMAT "\n", minv);
17512
+ if (seq-> minv != default_minv)
17513
+ appendPQExpBuffer(query, " MINVALUE " INT64_FORMAT "\n", seq-> minv);
17435
17514
else
17436
17515
appendPQExpBufferStr(query, " NO MINVALUE\n");
17437
17516
17438
- if (maxv != default_maxv)
17439
- appendPQExpBuffer(query, " MAXVALUE " INT64_FORMAT "\n", maxv);
17517
+ if (seq-> maxv != default_maxv)
17518
+ appendPQExpBuffer(query, " MAXVALUE " INT64_FORMAT "\n", seq-> maxv);
17440
17519
else
17441
17520
appendPQExpBufferStr(query, " NO MAXVALUE\n");
17442
17521
17443
17522
appendPQExpBuffer(query,
17444
17523
" CACHE " INT64_FORMAT "%s",
17445
- cache, (cycled ? "\n CYCLE" : ""));
17524
+ seq-> cache, (seq-> cycled ? "\n CYCLE" : ""));
17446
17525
17447
17526
if (tbinfo->is_identity_sequence)
17448
17527
{
@@ -17528,6 +17607,8 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo)
17528
17607
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
17529
17608
tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
17530
17609
17610
+ if (fout->remoteVersion < 100000)
17611
+ pg_free(seq);
17531
17612
destroyPQExpBuffer(query);
17532
17613
destroyPQExpBuffer(delqry);
17533
17614
free(qseqname);
0 commit comments