00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <time.h>
00018 #include <unistd.h>
00019 #include <signal.h>
00020 #ifdef HAVE_GETOPT_H
00021 #include <getopt.h>
00022 #endif
00023
00024 #include "access/htup_details.h"
00025 #include "bootstrap/bootstrap.h"
00026 #include "catalog/index.h"
00027 #include "catalog/pg_collation.h"
00028 #include "catalog/pg_type.h"
00029 #include "libpq/pqsignal.h"
00030 #include "miscadmin.h"
00031 #include "nodes/makefuncs.h"
00032 #include "postmaster/bgwriter.h"
00033 #include "postmaster/startup.h"
00034 #include "postmaster/walwriter.h"
00035 #include "replication/walreceiver.h"
00036 #include "storage/bufmgr.h"
00037 #include "storage/bufpage.h"
00038 #include "storage/ipc.h"
00039 #include "storage/proc.h"
00040 #include "tcop/tcopprot.h"
00041 #include "utils/builtins.h"
00042 #include "utils/fmgroids.h"
00043 #include "utils/memutils.h"
00044 #include "utils/ps_status.h"
00045 #include "utils/rel.h"
00046 #include "utils/relmapper.h"
00047 #include "utils/tqual.h"
00048
00049 extern int optind;
00050 extern char *optarg;
00051
00052 uint32 bootstrap_data_checksum_version = 0;
00053
00054
00055 #define ALLOC(t, c) ((t *) calloc((unsigned)(c), sizeof(t)))
00056
00057 static void CheckerModeMain(void);
00058 static void BootstrapModeMain(void);
00059 static void bootstrap_signals(void);
00060 static void ShutdownAuxiliaryProcess(int code, Datum arg);
00061 static Form_pg_attribute AllocateAttribute(void);
00062 static Oid gettype(char *type);
00063 static void cleanup(void);
00064
00065
00066
00067
00068
00069
00070 AuxProcType MyAuxProcType = NotAnAuxProcess;
00071
00072 Relation boot_reldesc;
00073
00074 Form_pg_attribute attrtypes[MAXATTR];
00075 int numattr;
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 struct typinfo
00088 {
00089 char name[NAMEDATALEN];
00090 Oid oid;
00091 Oid elem;
00092 int16 len;
00093 bool byval;
00094 char align;
00095 char storage;
00096 Oid collation;
00097 Oid inproc;
00098 Oid outproc;
00099 };
00100
00101 static const struct typinfo TypInfo[] = {
00102 {"bool", BOOLOID, 0, 1, true, 'c', 'p', InvalidOid,
00103 F_BOOLIN, F_BOOLOUT},
00104 {"bytea", BYTEAOID, 0, -1, false, 'i', 'x', InvalidOid,
00105 F_BYTEAIN, F_BYTEAOUT},
00106 {"char", CHAROID, 0, 1, true, 'c', 'p', InvalidOid,
00107 F_CHARIN, F_CHAROUT},
00108 {"int2", INT2OID, 0, 2, true, 's', 'p', InvalidOid,
00109 F_INT2IN, F_INT2OUT},
00110 {"int4", INT4OID, 0, 4, true, 'i', 'p', InvalidOid,
00111 F_INT4IN, F_INT4OUT},
00112 {"float4", FLOAT4OID, 0, 4, FLOAT4PASSBYVAL, 'i', 'p', InvalidOid,
00113 F_FLOAT4IN, F_FLOAT4OUT},
00114 {"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'c', 'p', InvalidOid,
00115 F_NAMEIN, F_NAMEOUT},
00116 {"regclass", REGCLASSOID, 0, 4, true, 'i', 'p', InvalidOid,
00117 F_REGCLASSIN, F_REGCLASSOUT},
00118 {"regproc", REGPROCOID, 0, 4, true, 'i', 'p', InvalidOid,
00119 F_REGPROCIN, F_REGPROCOUT},
00120 {"regtype", REGTYPEOID, 0, 4, true, 'i', 'p', InvalidOid,
00121 F_REGTYPEIN, F_REGTYPEOUT},
00122 {"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
00123 F_TEXTIN, F_TEXTOUT},
00124 {"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid,
00125 F_OIDIN, F_OIDOUT},
00126 {"tid", TIDOID, 0, 6, false, 's', 'p', InvalidOid,
00127 F_TIDIN, F_TIDOUT},
00128 {"xid", XIDOID, 0, 4, true, 'i', 'p', InvalidOid,
00129 F_XIDIN, F_XIDOUT},
00130 {"cid", CIDOID, 0, 4, true, 'i', 'p', InvalidOid,
00131 F_CIDIN, F_CIDOUT},
00132 {"pg_node_tree", PGNODETREEOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
00133 F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
00134 {"int2vector", INT2VECTOROID, INT2OID, -1, false, 'i', 'p', InvalidOid,
00135 F_INT2VECTORIN, F_INT2VECTOROUT},
00136 {"oidvector", OIDVECTOROID, OIDOID, -1, false, 'i', 'p', InvalidOid,
00137 F_OIDVECTORIN, F_OIDVECTOROUT},
00138 {"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x', InvalidOid,
00139 F_ARRAY_IN, F_ARRAY_OUT},
00140 {"_text", 1009, TEXTOID, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
00141 F_ARRAY_IN, F_ARRAY_OUT},
00142 {"_oid", 1028, OIDOID, -1, false, 'i', 'x', InvalidOid,
00143 F_ARRAY_IN, F_ARRAY_OUT},
00144 {"_char", 1002, CHAROID, -1, false, 'i', 'x', InvalidOid,
00145 F_ARRAY_IN, F_ARRAY_OUT},
00146 {"_aclitem", 1034, ACLITEMOID, -1, false, 'i', 'x', InvalidOid,
00147 F_ARRAY_IN, F_ARRAY_OUT}
00148 };
00149
00150 static const int n_types = sizeof(TypInfo) / sizeof(struct typinfo);
00151
00152 struct typmap
00153 {
00154 Oid am_oid;
00155 FormData_pg_type am_typ;
00156 };
00157
00158 static struct typmap **Typ = NULL;
00159 static struct typmap *Ap = NULL;
00160
00161 static Datum values[MAXATTR];
00162 static bool Nulls[MAXATTR];
00163
00164 static MemoryContext nogc = NULL;
00165
00166
00167
00168
00169
00170
00171
00172 typedef struct _IndexList
00173 {
00174 Oid il_heap;
00175 Oid il_ind;
00176 IndexInfo *il_info;
00177 struct _IndexList *il_next;
00178 } IndexList;
00179
00180 static IndexList *ILHead = NULL;
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 void
00192 AuxiliaryProcessMain(int argc, char *argv[])
00193 {
00194 char *progname = argv[0];
00195 int flag;
00196 char *userDoption = NULL;
00197
00198
00199
00200
00201 MyProcPid = getpid();
00202
00203 MyStartTime = time(NULL);
00204
00205
00206
00207
00208
00209
00210 if (!IsUnderPostmaster)
00211 MemoryContextInit();
00212
00213
00214 if (my_exec_path[0] == '\0')
00215 {
00216 if (find_my_exec(progname, my_exec_path) < 0)
00217 elog(FATAL, "%s: could not locate my own executable path",
00218 progname);
00219 }
00220
00221
00222
00223
00224
00225
00226 if (!IsUnderPostmaster)
00227 InitializeGUCOptions();
00228
00229
00230 if (argc > 1 && strcmp(argv[1], "--boot") == 0)
00231 {
00232 argv++;
00233 argc--;
00234 }
00235
00236
00237 MyAuxProcType = CheckerProcess;
00238
00239 while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:x:-:")) != -1)
00240 {
00241 switch (flag)
00242 {
00243 case 'B':
00244 SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
00245 break;
00246 case 'D':
00247 userDoption = strdup(optarg);
00248 break;
00249 case 'd':
00250 {
00251
00252 char *debugstr = palloc(strlen("debug") + strlen(optarg) + 1);
00253
00254 sprintf(debugstr, "debug%s", optarg);
00255 SetConfigOption("log_min_messages", debugstr,
00256 PGC_POSTMASTER, PGC_S_ARGV);
00257 SetConfigOption("client_min_messages", debugstr,
00258 PGC_POSTMASTER, PGC_S_ARGV);
00259 pfree(debugstr);
00260 }
00261 break;
00262 case 'F':
00263 SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
00264 break;
00265 case 'k':
00266 bootstrap_data_checksum_version = PG_DATA_CHECKSUM_VERSION;
00267 break;
00268 case 'r':
00269 strlcpy(OutputFileName, optarg, MAXPGPATH);
00270 break;
00271 case 'x':
00272 MyAuxProcType = atoi(optarg);
00273 break;
00274 case 'c':
00275 case '-':
00276 {
00277 char *name,
00278 *value;
00279
00280 ParseLongOption(optarg, &name, &value);
00281 if (!value)
00282 {
00283 if (flag == '-')
00284 ereport(ERROR,
00285 (errcode(ERRCODE_SYNTAX_ERROR),
00286 errmsg("--%s requires a value",
00287 optarg)));
00288 else
00289 ereport(ERROR,
00290 (errcode(ERRCODE_SYNTAX_ERROR),
00291 errmsg("-c %s requires a value",
00292 optarg)));
00293 }
00294
00295 SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV);
00296 free(name);
00297 if (value)
00298 free(value);
00299 break;
00300 }
00301 default:
00302 write_stderr("Try \"%s --help\" for more information.\n",
00303 progname);
00304 proc_exit(1);
00305 break;
00306 }
00307 }
00308
00309 if (argc != optind)
00310 {
00311 write_stderr("%s: invalid command-line arguments\n", progname);
00312 proc_exit(1);
00313 }
00314
00315
00316
00317
00318 if (IsUnderPostmaster)
00319 {
00320 const char *statmsg;
00321
00322 switch (MyAuxProcType)
00323 {
00324 case StartupProcess:
00325 statmsg = "startup process";
00326 break;
00327 case BgWriterProcess:
00328 statmsg = "writer process";
00329 break;
00330 case CheckpointerProcess:
00331 statmsg = "checkpointer process";
00332 break;
00333 case WalWriterProcess:
00334 statmsg = "wal writer process";
00335 break;
00336 case WalReceiverProcess:
00337 statmsg = "wal receiver process";
00338 break;
00339 default:
00340 statmsg = "??? process";
00341 break;
00342 }
00343 init_ps_display(statmsg, "", "", "");
00344 }
00345
00346
00347 if (!IsUnderPostmaster)
00348 {
00349 if (!SelectConfigFiles(userDoption, progname))
00350 proc_exit(1);
00351 }
00352
00353
00354 Assert(DataDir);
00355 ValidatePgVersion(DataDir);
00356
00357
00358 if (!IsUnderPostmaster)
00359 ChangeToDataDir();
00360
00361
00362 if (!IsUnderPostmaster)
00363 CreateDataDirLockFile(false);
00364
00365 SetProcessingMode(BootstrapProcessing);
00366 IgnoreSystemIndexes = true;
00367
00368
00369 if (!IsUnderPostmaster)
00370 InitializeMaxBackends();
00371
00372 BaseInit();
00373
00374
00375
00376
00377
00378
00379 if (IsUnderPostmaster)
00380 {
00381
00382
00383
00384
00385 #ifndef EXEC_BACKEND
00386 InitAuxiliaryProcess();
00387 #endif
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 ProcSignalInit(MaxBackends + MyAuxProcType + 1);
00401
00402
00403 InitBufferPoolBackend();
00404
00405
00406 on_shmem_exit(ShutdownAuxiliaryProcess, 0);
00407 }
00408
00409
00410
00411
00412 SetProcessingMode(NormalProcessing);
00413
00414 switch (MyAuxProcType)
00415 {
00416 case CheckerProcess:
00417
00418 CheckerModeMain();
00419 proc_exit(1);
00420
00421 case BootstrapProcess:
00422 bootstrap_signals();
00423 BootStrapXLOG();
00424 BootstrapModeMain();
00425 proc_exit(1);
00426
00427 case StartupProcess:
00428
00429 StartupProcessMain();
00430 proc_exit(1);
00431
00432 case BgWriterProcess:
00433
00434 BackgroundWriterMain();
00435 proc_exit(1);
00436
00437 case CheckpointerProcess:
00438
00439 CheckpointerMain();
00440 proc_exit(1);
00441
00442 case WalWriterProcess:
00443
00444 InitXLOGAccess();
00445 WalWriterMain();
00446 proc_exit(1);
00447
00448 case WalReceiverProcess:
00449
00450 WalReceiverMain();
00451 proc_exit(1);
00452
00453 default:
00454 elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType);
00455 proc_exit(1);
00456 }
00457 }
00458
00459
00460
00461
00462
00463
00464
00465 static void
00466 CheckerModeMain(void)
00467 {
00468 proc_exit(0);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478 static void
00479 BootstrapModeMain(void)
00480 {
00481 int i;
00482
00483 Assert(!IsUnderPostmaster);
00484
00485 SetProcessingMode(BootstrapProcessing);
00486
00487
00488
00489
00490 InitProcess();
00491
00492 InitPostgres(NULL, InvalidOid, NULL, NULL);
00493
00494
00495 for (i = 0; i < MAXATTR; i++)
00496 {
00497 attrtypes[i] = NULL;
00498 Nulls[i] = false;
00499 }
00500
00501
00502
00503
00504 boot_yyparse();
00505
00506
00507
00508
00509
00510 RelationMapFinishBootstrap();
00511
00512
00513 cleanup();
00514 proc_exit(0);
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 static void
00527 bootstrap_signals(void)
00528 {
00529 if (IsUnderPostmaster)
00530 {
00531
00532
00533
00534
00535 #ifdef HAVE_SETSID
00536 if (setsid() < 0)
00537 elog(FATAL, "setsid() failed: %m");
00538 #endif
00539
00540
00541
00542
00543 pqsignal(SIGHUP, SIG_IGN);
00544 pqsignal(SIGINT, SIG_IGN);
00545 pqsignal(SIGTERM, die);
00546 pqsignal(SIGQUIT, quickdie);
00547 pqsignal(SIGALRM, SIG_IGN);
00548 pqsignal(SIGPIPE, SIG_IGN);
00549 pqsignal(SIGUSR1, SIG_IGN);
00550 pqsignal(SIGUSR2, SIG_IGN);
00551
00552
00553
00554
00555 pqsignal(SIGCHLD, SIG_DFL);
00556 pqsignal(SIGTTIN, SIG_DFL);
00557 pqsignal(SIGTTOU, SIG_DFL);
00558 pqsignal(SIGCONT, SIG_DFL);
00559 pqsignal(SIGWINCH, SIG_DFL);
00560
00561
00562
00563
00564 PG_SETMASK(&UnBlockSig);
00565 }
00566 else
00567 {
00568
00569 pqsignal(SIGHUP, die);
00570 pqsignal(SIGINT, die);
00571 pqsignal(SIGTERM, die);
00572 pqsignal(SIGQUIT, die);
00573 }
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583 static void
00584 ShutdownAuxiliaryProcess(int code, Datum arg)
00585 {
00586 LWLockReleaseAll();
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 void
00599 boot_openrel(char *relname)
00600 {
00601 int i;
00602 struct typmap **app;
00603 Relation rel;
00604 HeapScanDesc scan;
00605 HeapTuple tup;
00606
00607 if (strlen(relname) >= NAMEDATALEN)
00608 relname[NAMEDATALEN - 1] = '\0';
00609
00610 if (Typ == NULL)
00611 {
00612
00613 rel = heap_open(TypeRelationId, NoLock);
00614 scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
00615 i = 0;
00616 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
00617 ++i;
00618 heap_endscan(scan);
00619 app = Typ = ALLOC(struct typmap *, i + 1);
00620 while (i-- > 0)
00621 *app++ = ALLOC(struct typmap, 1);
00622 *app = NULL;
00623 scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
00624 app = Typ;
00625 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
00626 {
00627 (*app)->am_oid = HeapTupleGetOid(tup);
00628 memcpy((char *) &(*app)->am_typ,
00629 (char *) GETSTRUCT(tup),
00630 sizeof((*app)->am_typ));
00631 app++;
00632 }
00633 heap_endscan(scan);
00634 heap_close(rel, NoLock);
00635 }
00636
00637 if (boot_reldesc != NULL)
00638 closerel(NULL);
00639
00640 elog(DEBUG4, "open relation %s, attrsize %d",
00641 relname, (int) ATTRIBUTE_FIXED_PART_SIZE);
00642
00643 boot_reldesc = heap_openrv(makeRangeVar(NULL, relname, -1), NoLock);
00644 numattr = boot_reldesc->rd_rel->relnatts;
00645 for (i = 0; i < numattr; i++)
00646 {
00647 if (attrtypes[i] == NULL)
00648 attrtypes[i] = AllocateAttribute();
00649 memmove((char *) attrtypes[i],
00650 (char *) boot_reldesc->rd_att->attrs[i],
00651 ATTRIBUTE_FIXED_PART_SIZE);
00652
00653 {
00654 Form_pg_attribute at = attrtypes[i];
00655
00656 elog(DEBUG4, "create attribute %d name %s len %d num %d type %u",
00657 i, NameStr(at->attname), at->attlen, at->attnum,
00658 at->atttypid);
00659 }
00660 }
00661 }
00662
00663
00664
00665
00666
00667 void
00668 closerel(char *name)
00669 {
00670 if (name)
00671 {
00672 if (boot_reldesc)
00673 {
00674 if (strcmp(RelationGetRelationName(boot_reldesc), name) != 0)
00675 elog(ERROR, "close of %s when %s was expected",
00676 name, RelationGetRelationName(boot_reldesc));
00677 }
00678 else
00679 elog(ERROR, "close of %s before any relation was opened",
00680 name);
00681 }
00682
00683 if (boot_reldesc == NULL)
00684 elog(ERROR, "no open relation to close");
00685 else
00686 {
00687 elog(DEBUG4, "close relation %s",
00688 RelationGetRelationName(boot_reldesc));
00689 heap_close(boot_reldesc, NoLock);
00690 boot_reldesc = NULL;
00691 }
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 void
00705 DefineAttr(char *name, char *type, int attnum)
00706 {
00707 Oid typeoid;
00708
00709 if (boot_reldesc != NULL)
00710 {
00711 elog(WARNING, "no open relations allowed with CREATE command");
00712 closerel(NULL);
00713 }
00714
00715 if (attrtypes[attnum] == NULL)
00716 attrtypes[attnum] = AllocateAttribute();
00717 MemSet(attrtypes[attnum], 0, ATTRIBUTE_FIXED_PART_SIZE);
00718
00719 namestrcpy(&attrtypes[attnum]->attname, name);
00720 elog(DEBUG4, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
00721 attrtypes[attnum]->attnum = attnum + 1;
00722
00723 typeoid = gettype(type);
00724
00725 if (Typ != NULL)
00726 {
00727 attrtypes[attnum]->atttypid = Ap->am_oid;
00728 attrtypes[attnum]->attlen = Ap->am_typ.typlen;
00729 attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
00730 attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
00731 attrtypes[attnum]->attalign = Ap->am_typ.typalign;
00732 attrtypes[attnum]->attcollation = Ap->am_typ.typcollation;
00733
00734 if (Ap->am_typ.typelem != InvalidOid && Ap->am_typ.typlen < 0)
00735 attrtypes[attnum]->attndims = 1;
00736 else
00737 attrtypes[attnum]->attndims = 0;
00738 }
00739 else
00740 {
00741 attrtypes[attnum]->atttypid = TypInfo[typeoid].oid;
00742 attrtypes[attnum]->attlen = TypInfo[typeoid].len;
00743 attrtypes[attnum]->attbyval = TypInfo[typeoid].byval;
00744 attrtypes[attnum]->attstorage = TypInfo[typeoid].storage;
00745 attrtypes[attnum]->attalign = TypInfo[typeoid].align;
00746 attrtypes[attnum]->attcollation = TypInfo[typeoid].collation;
00747
00748 if (TypInfo[typeoid].elem != InvalidOid &&
00749 attrtypes[attnum]->attlen < 0)
00750 attrtypes[attnum]->attndims = 1;
00751 else
00752 attrtypes[attnum]->attndims = 0;
00753 }
00754
00755 attrtypes[attnum]->attstattarget = -1;
00756 attrtypes[attnum]->attcacheoff = -1;
00757 attrtypes[attnum]->atttypmod = -1;
00758 attrtypes[attnum]->attislocal = true;
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 #define MARKNOTNULL(att) \
00769 ((att)->attlen > 0 || \
00770 (att)->atttypid == OIDVECTOROID || \
00771 (att)->atttypid == INT2VECTOROID)
00772
00773 if (MARKNOTNULL(attrtypes[attnum]))
00774 {
00775 int i;
00776
00777 for (i = 0; i < attnum; i++)
00778 {
00779 if (!MARKNOTNULL(attrtypes[i]))
00780 break;
00781 }
00782 if (i == attnum)
00783 attrtypes[attnum]->attnotnull = true;
00784 }
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 void
00796 InsertOneTuple(Oid objectid)
00797 {
00798 HeapTuple tuple;
00799 TupleDesc tupDesc;
00800 int i;
00801
00802 elog(DEBUG4, "inserting row oid %u, %d columns", objectid, numattr);
00803
00804 tupDesc = CreateTupleDesc(numattr,
00805 RelationGetForm(boot_reldesc)->relhasoids,
00806 attrtypes);
00807 tuple = heap_form_tuple(tupDesc, values, Nulls);
00808 if (objectid != (Oid) 0)
00809 HeapTupleSetOid(tuple, objectid);
00810 pfree(tupDesc);
00811
00812 simple_heap_insert(boot_reldesc, tuple);
00813 heap_freetuple(tuple);
00814 elog(DEBUG4, "row inserted");
00815
00816
00817
00818
00819 for (i = 0; i < numattr; i++)
00820 Nulls[i] = false;
00821 }
00822
00823
00824
00825
00826
00827 void
00828 InsertOneValue(char *value, int i)
00829 {
00830 Oid typoid;
00831 int16 typlen;
00832 bool typbyval;
00833 char typalign;
00834 char typdelim;
00835 Oid typioparam;
00836 Oid typinput;
00837 Oid typoutput;
00838 char *prt;
00839
00840 AssertArg(i >= 0 && i < MAXATTR);
00841
00842 elog(DEBUG4, "inserting column %d value \"%s\"", i, value);
00843
00844 typoid = boot_reldesc->rd_att->attrs[i]->atttypid;
00845
00846 boot_get_type_io_data(typoid,
00847 &typlen, &typbyval, &typalign,
00848 &typdelim, &typioparam,
00849 &typinput, &typoutput);
00850
00851 values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
00852 prt = OidOutputFunctionCall(typoutput, values[i]);
00853 elog(DEBUG4, "inserted -> %s", prt);
00854 pfree(prt);
00855 }
00856
00857
00858
00859
00860
00861 void
00862 InsertOneNull(int i)
00863 {
00864 elog(DEBUG4, "inserting column %d NULL", i);
00865 Assert(i >= 0 && i < MAXATTR);
00866 values[i] = PointerGetDatum(NULL);
00867 Nulls[i] = true;
00868 }
00869
00870
00871
00872
00873
00874 static void
00875 cleanup(void)
00876 {
00877 if (boot_reldesc != NULL)
00878 closerel(NULL);
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 static Oid
00893 gettype(char *type)
00894 {
00895 int i;
00896 Relation rel;
00897 HeapScanDesc scan;
00898 HeapTuple tup;
00899 struct typmap **app;
00900
00901 if (Typ != NULL)
00902 {
00903 for (app = Typ; *app != NULL; app++)
00904 {
00905 if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)
00906 {
00907 Ap = *app;
00908 return (*app)->am_oid;
00909 }
00910 }
00911 }
00912 else
00913 {
00914 for (i = 0; i < n_types; i++)
00915 {
00916 if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0)
00917 return i;
00918 }
00919 elog(DEBUG4, "external type: %s", type);
00920 rel = heap_open(TypeRelationId, NoLock);
00921 scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
00922 i = 0;
00923 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
00924 ++i;
00925 heap_endscan(scan);
00926 app = Typ = ALLOC(struct typmap *, i + 1);
00927 while (i-- > 0)
00928 *app++ = ALLOC(struct typmap, 1);
00929 *app = NULL;
00930 scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
00931 app = Typ;
00932 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
00933 {
00934 (*app)->am_oid = HeapTupleGetOid(tup);
00935 memmove((char *) &(*app++)->am_typ,
00936 (char *) GETSTRUCT(tup),
00937 sizeof((*app)->am_typ));
00938 }
00939 heap_endscan(scan);
00940 heap_close(rel, NoLock);
00941 return gettype(type);
00942 }
00943 elog(ERROR, "unrecognized type \"%s\"", type);
00944
00945 return 0;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 void
00959 boot_get_type_io_data(Oid typid,
00960 int16 *typlen,
00961 bool *typbyval,
00962 char *typalign,
00963 char *typdelim,
00964 Oid *typioparam,
00965 Oid *typinput,
00966 Oid *typoutput)
00967 {
00968 if (Typ != NULL)
00969 {
00970
00971 struct typmap **app;
00972 struct typmap *ap;
00973
00974 app = Typ;
00975 while (*app && (*app)->am_oid != typid)
00976 ++app;
00977 ap = *app;
00978 if (ap == NULL)
00979 elog(ERROR, "type OID %u not found in Typ list", typid);
00980
00981 *typlen = ap->am_typ.typlen;
00982 *typbyval = ap->am_typ.typbyval;
00983 *typalign = ap->am_typ.typalign;
00984 *typdelim = ap->am_typ.typdelim;
00985
00986
00987 if (OidIsValid(ap->am_typ.typelem))
00988 *typioparam = ap->am_typ.typelem;
00989 else
00990 *typioparam = typid;
00991
00992 *typinput = ap->am_typ.typinput;
00993 *typoutput = ap->am_typ.typoutput;
00994 }
00995 else
00996 {
00997
00998 int typeindex;
00999
01000 for (typeindex = 0; typeindex < n_types; typeindex++)
01001 {
01002 if (TypInfo[typeindex].oid == typid)
01003 break;
01004 }
01005 if (typeindex >= n_types)
01006 elog(ERROR, "type OID %u not found in TypInfo", typid);
01007
01008 *typlen = TypInfo[typeindex].len;
01009 *typbyval = TypInfo[typeindex].byval;
01010 *typalign = TypInfo[typeindex].align;
01011
01012 *typdelim = ',';
01013
01014
01015 if (OidIsValid(TypInfo[typeindex].elem))
01016 *typioparam = TypInfo[typeindex].elem;
01017 else
01018 *typioparam = typid;
01019
01020 *typinput = TypInfo[typeindex].inproc;
01021 *typoutput = TypInfo[typeindex].outproc;
01022 }
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032 static Form_pg_attribute
01033 AllocateAttribute(void)
01034 {
01035 Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_FIXED_PART_SIZE);
01036
01037 if (!PointerIsValid(attribute))
01038 elog(FATAL, "out of memory");
01039 MemSet(attribute, 0, ATTRIBUTE_FIXED_PART_SIZE);
01040
01041 return attribute;
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058 char *
01059 MapArrayTypeName(char *s)
01060 {
01061 int i,
01062 j;
01063 static char newStr[NAMEDATALEN];
01064
01065 if (s == NULL || s[0] == '\0')
01066 return s;
01067
01068 j = 1;
01069 newStr[0] = '_';
01070 for (i = 0; i < NAMEDATALEN - 1 && s[i] != '['; i++, j++)
01071 newStr[j] = s[i];
01072
01073 newStr[j] = '\0';
01074
01075 return newStr;
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090 void
01091 index_register(Oid heap,
01092 Oid ind,
01093 IndexInfo *indexInfo)
01094 {
01095 IndexList *newind;
01096 MemoryContext oldcxt;
01097
01098
01099
01100
01101
01102
01103
01104 if (nogc == NULL)
01105 nogc = AllocSetContextCreate(NULL,
01106 "BootstrapNoGC",
01107 ALLOCSET_DEFAULT_MINSIZE,
01108 ALLOCSET_DEFAULT_INITSIZE,
01109 ALLOCSET_DEFAULT_MAXSIZE);
01110
01111 oldcxt = MemoryContextSwitchTo(nogc);
01112
01113 newind = (IndexList *) palloc(sizeof(IndexList));
01114 newind->il_heap = heap;
01115 newind->il_ind = ind;
01116 newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
01117
01118 memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
01119
01120 newind->il_info->ii_Expressions = (List *)
01121 copyObject(indexInfo->ii_Expressions);
01122 newind->il_info->ii_ExpressionsState = NIL;
01123
01124 newind->il_info->ii_Predicate = (List *)
01125 copyObject(indexInfo->ii_Predicate);
01126 newind->il_info->ii_PredicateState = NIL;
01127
01128 Assert(indexInfo->ii_ExclusionOps == NULL);
01129 Assert(indexInfo->ii_ExclusionProcs == NULL);
01130 Assert(indexInfo->ii_ExclusionStrats == NULL);
01131
01132 newind->il_next = ILHead;
01133 ILHead = newind;
01134
01135 MemoryContextSwitchTo(oldcxt);
01136 }
01137
01138
01139
01140
01141
01142 void
01143 build_indices(void)
01144 {
01145 for (; ILHead != NULL; ILHead = ILHead->il_next)
01146 {
01147 Relation heap;
01148 Relation ind;
01149
01150
01151 heap = heap_open(ILHead->il_heap, NoLock);
01152 ind = index_open(ILHead->il_ind, NoLock);
01153
01154 index_build(heap, ind, ILHead->il_info, false, false);
01155
01156 index_close(ind, NoLock);
01157 heap_close(heap, NoLock);
01158 }
01159 }