bootstrap.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:26k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * bootstrap.c
  4.  *   routines to support running postgres in 'bootstrap' mode
  5.  * bootstrap mode is used to create the initial template database
  6.  *
  7.  * Copyright (c) 1994, Regents of the University of California
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.60.2.1 1999/08/02 05:56:52 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <unistd.h>
  15. #include <time.h>
  16. #include <signal.h>
  17. #include <setjmp.h>
  18. #define BOOTSTRAP_INCLUDE /* mask out stuff in tcop/tcopprot.h */
  19. #include "postgres.h"
  20. #ifdef HAVE_GETOPT_H
  21. #include <getopt.h>
  22. #endif
  23. #include "access/genam.h"
  24. #include "access/heapam.h"
  25. #include "bootstrap/bootstrap.h"
  26. #include "catalog/catname.h"
  27. #include "catalog/index.h"
  28. #include "catalog/pg_type.h"
  29. #include "libpq/pqsignal.h"
  30. #include "miscadmin.h"
  31. #include "tcop/tcopprot.h"
  32. #include "utils/builtins.h"
  33. #include "utils/lsyscache.h"
  34. #include "utils/portal.h"
  35. #define ALLOC(t, c) (t *)calloc((unsigned)(c), sizeof(t))
  36. #define FIRST_TYPE_OID 16 /* OID of the first type */
  37. extern int Int_yyparse(void);
  38. static hashnode *AddStr(char *str, int strlength, int mderef);
  39. static Form_pg_attribute AllocateAttribute(void);
  40. static bool BootstrapAlreadySeen(Oid id);
  41. static int CompHash(char *str, int len);
  42. static hashnode *FindStr(char *str, int length, hashnode *mderef);
  43. static Oid gettype(char *type);
  44. static void cleanup(void);
  45. /* ----------------
  46.  * global variables
  47.  * ----------------
  48.  */
  49. /*
  50.  * In the lexical analyzer, we need to get the reference number quickly from
  51.  * the string, and the string from the reference number.  Thus we have
  52.  * as our data structure a hash table, where the hashing key taken from
  53.  * the particular string.  The hash table is chained.  One of the fields
  54.  * of the hash table node is an index into the array of character pointers.
  55.  * The unique index number that every string is assigned is simply the
  56.  * position of its string pointer in the array of string pointers.
  57.  */
  58. #define STRTABLESIZE 10000
  59. #define HASHTABLESIZE 503
  60. /* Hash function numbers */
  61. #define NUM 23
  62. #define NUMSQR 529
  63. #define NUMCUBE 12167
  64. char    *strtable[STRTABLESIZE];
  65. hashnode   *hashtable[HASHTABLESIZE];
  66. static int strtable_end = -1; /* Tells us last occupied string space */
  67. /*-
  68.  * Basic information associated with each type.  This is used before
  69.  * pg_type is created.
  70.  *
  71.  * XXX several of these input/output functions do catalog scans
  72.  * (e.g., F_REGPROCIN scans pg_proc). this obviously creates some
  73.  * order dependencies in the catalog creation process.
  74.  */
  75. struct typinfo
  76. {
  77. char name[NAMEDATALEN];
  78. Oid oid;
  79. Oid elem;
  80. int16 len;
  81. Oid inproc;
  82. Oid outproc;
  83. };
  84. static struct typinfo Procid[] = {
  85. {"bool", 16, 0, 1, F_BOOLIN, F_BOOLOUT},
  86. {"bytea", 17, 0, -1, F_BYTEAIN, F_BYTEAOUT},
  87. {"char", 18, 0, 1, F_CHARIN, F_CHAROUT},
  88. {"name", 19, 0, NAMEDATALEN, F_NAMEIN, F_NAMEOUT},
  89. {"dummy", 20, 0, 16, 0, 0},
  90. /*   { "dt",   20,  0,  4, F_DTIN, F_DTOUT}, */
  91. {"int2", 21, 0, 2, F_INT2IN, F_INT2OUT},
  92. {"int28", 22, 0, 16, F_INT28IN, F_INT28OUT},
  93. {"int4", 23, 0, 4, F_INT4IN, F_INT4OUT},
  94. {"regproc", 24, 0, 4, F_REGPROCIN, F_REGPROCOUT},
  95. {"text", 25, 0, -1, F_TEXTIN, F_TEXTOUT},
  96. {"oid", 26, 0, 4, F_INT4IN, F_INT4OUT},
  97. {"tid", 27, 0, 6, F_TIDIN, F_TIDOUT},
  98. {"xid", 28, 0, 5, F_XIDIN, F_XIDOUT},
  99. {"iid", 29, 0, 1, F_CIDIN, F_CIDOUT},
  100. {"oid8", 30, 0, 32, F_OID8IN, F_OID8OUT},
  101. {"smgr", 210, 0, 2, F_SMGRIN, F_SMGROUT},
  102. {"_int4", 1007, 23, -1, F_ARRAY_IN, F_ARRAY_OUT},
  103. {"_aclitem", 1034, 1033, -1, F_ARRAY_IN, F_ARRAY_OUT}
  104. };
  105. static int n_types = sizeof(Procid) / sizeof(struct typinfo);
  106. struct typmap
  107. { /* a hack */
  108. Oid am_oid;
  109. FormData_pg_type am_typ;
  110. };
  111. static struct typmap **Typ = (struct typmap **) NULL;
  112. static struct typmap *Ap = (struct typmap *) NULL;
  113. static int Warnings = 0;
  114. static char Blanks[MAXATTR];
  115. static char *relname; /* current relation name */
  116. Form_pg_attribute attrtypes[MAXATTR]; /* points to attribute info */
  117. static char *values[MAXATTR]; /* cooresponding attribute values */
  118. int numattr; /* number of attributes for cur. rel */
  119. extern bool disableFsync; /* do not fsync the database */
  120. int DebugMode;
  121. static GlobalMemory nogc = (GlobalMemory) NULL; /* special no-gc mem
  122.  * context */
  123. extern int optind;
  124. extern char *optarg;
  125. /*
  126.  * At bootstrap time, we first declare all the indices to be built, and
  127.  * then build them.  The IndexList structure stores enough information
  128.  * to allow us to build the indices after they've been declared.
  129.  */
  130. typedef struct _IndexList
  131. {
  132. char    *il_heap;
  133. char    *il_ind;
  134. int il_natts;
  135. AttrNumber *il_attnos;
  136. uint16 il_nparams;
  137. Datum    *il_params;
  138. FuncIndexInfo *il_finfo;
  139. PredInfo   *il_predInfo;
  140. struct _IndexList *il_next;
  141. } IndexList;
  142. static IndexList *ILHead = (IndexList *) NULL;
  143. typedef void (*sig_func) ();
  144. /* ----------------------------------------------------------------
  145.  * misc functions
  146.  * ----------------------------------------------------------------
  147.  */
  148. /* ----------------
  149.  * error handling / abort routines
  150.  * ----------------
  151.  */
  152. void
  153. err_out(void)
  154. {
  155. Warnings++;
  156. cleanup();
  157. }
  158. /* usage:
  159.    usage help for the bootstrap backen
  160. */
  161. static void
  162. usage(void)
  163. {
  164. fprintf(stderr, "Usage: postgres -boot [-d] [-C] [-F] [-O] [-Q] ");
  165. fprintf(stderr, "[-P portno] [dbName]n");
  166. fprintf(stderr, "     d: debug moden");
  167. fprintf(stderr, "     C: disable version checkingn");
  168. fprintf(stderr, "     F: turn off fsyncn");
  169. fprintf(stderr, "     O: set BootstrapProcessing moden");
  170. fprintf(stderr, "     P portno: specify port numbern");
  171. proc_exit(1);
  172. }
  173. int
  174. BootstrapMain(int argc, char *argv[])
  175. /* ----------------------------------------------------------------
  176.  *  The main loop for handling the backend in bootstrap mode
  177.  *  the bootstrap mode is used to initialize the template database
  178.  *  the bootstrap backend doesn't speak SQL, but instead expects
  179.  *  commands in a special bootstrap language.
  180.  *
  181.  *  The arguments passed in to BootstrapMain are the run-time arguments
  182.  *  without the argument '-boot', the caller is required to have
  183.  *  removed -boot from the run-time args
  184.  * ----------------------------------------------------------------
  185.  */
  186. {
  187. int i;
  188. int portFd = -1;
  189. char    *dbName;
  190. int flag;
  191. int override = 1; /* use BootstrapProcessing or
  192.  * InitProcessing mode */
  193. extern int optind;
  194. extern char *optarg;
  195. /* ----------------
  196.  * initialize signal handlers
  197.  * ----------------
  198.  */
  199. pqsignal(SIGINT, (sig_func) die);
  200. pqsignal(SIGHUP, (sig_func) die);
  201. pqsignal(SIGTERM, (sig_func) die);
  202. /* --------------------
  203.  * initialize globals
  204.  * -------------------
  205.  */
  206. MyProcPid = getpid();
  207. /* ----------------
  208.  * process command arguments
  209.  * ----------------
  210.  */
  211. /* Set defaults, to be overriden by explicit options below */
  212. Quiet = false;
  213. Noversion = false;
  214. dbName = NULL;
  215. DataDir = getenv("PGDATA"); /* Null if no PGDATA variable */
  216. while ((flag = getopt(argc, argv, "D:dCOQP:F")) != EOF)
  217. {
  218. switch (flag)
  219. {
  220. case 'D':
  221. DataDir = optarg;
  222. break;
  223. case 'd':
  224. DebugMode = true; /* print out debugging info while
  225.  * parsing */
  226. break;
  227. case 'C':
  228. Noversion = true;
  229. break;
  230. case 'F':
  231. disableFsync = true;
  232. break;
  233. case 'O':
  234. override = true;
  235. break;
  236. case 'Q':
  237. Quiet = true;
  238. break;
  239. case 'P': /* specify port */
  240. portFd = atoi(optarg);
  241. break;
  242. default:
  243. usage();
  244. break;
  245. }
  246. } /* while */
  247. if (argc - optind > 1)
  248. usage();
  249. else if (argc - optind == 1)
  250. dbName = argv[optind];
  251. if (!DataDir)
  252. {
  253. fprintf(stderr, "%s does not know where to find the database system "
  254. "data.  You must specify the directory that contains the "
  255. "database system either by specifying the -D invocation "
  256.  "option or by setting the PGDATA environment variable.nn",
  257. argv[0]);
  258. proc_exit(1);
  259. }
  260. if (dbName == NULL)
  261. {
  262. dbName = getenv("USER");
  263. if (dbName == NULL)
  264. {
  265. fputs("bootstrap backend: failed, no db name specifiedn", stderr);
  266. fputs("          and no USER enviroment variablen", stderr);
  267. proc_exit(1);
  268. }
  269. }
  270. /* ----------------
  271.  * initialize input fd
  272.  * ----------------
  273.  */
  274. if (IsUnderPostmaster && portFd < 0)
  275. {
  276. fputs("backend: failed, no -P option with -postmaster opt.n", stderr);
  277. proc_exit(1);
  278. }
  279. /* ----------------
  280.  * backend initialization
  281.  * ----------------
  282.  */
  283. SetProcessingMode((override) ? BootstrapProcessing : InitProcessing);
  284. InitPostgres(dbName);
  285. LockDisable(true);
  286. for (i = 0; i < MAXATTR; i++)
  287. {
  288. attrtypes[i] = (Form_pg_attribute) NULL;
  289. Blanks[i] = ' ';
  290. }
  291. for (i = 0; i < STRTABLESIZE; ++i)
  292. strtable[i] = NULL;
  293. for (i = 0; i < HASHTABLESIZE; ++i)
  294. hashtable[i] = NULL;
  295. /* ----------------
  296.  * abort processing resumes here
  297.  * ----------------
  298.  */
  299. pqsignal(SIGHUP, handle_warn);
  300. if (sigsetjmp(Warn_restart, 1) != 0)
  301. {
  302. Warnings++;
  303. AbortCurrentTransaction();
  304. }
  305. /* ----------------
  306.  * process input.
  307.  * ----------------
  308.  */
  309. /*
  310.  * the sed script boot.sed renamed yyparse to Int_yyparse for the
  311.  * bootstrap parser to avoid conflicts with the normal SQL parser
  312.  */
  313. Int_yyparse();
  314. /* clean up processing */
  315. StartTransactionCommand();
  316. cleanup();
  317. /* not reached, here to make compiler happy */
  318. return 0;
  319. }
  320. /* ----------------------------------------------------------------
  321.  * MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
  322.  * ----------------------------------------------------------------
  323.  */
  324. /* ----------------
  325.  * boot_openrel
  326.  * ----------------
  327.  */
  328. void
  329. boot_openrel(char *relname)
  330. {
  331. int i;
  332. struct typmap **app;
  333. Relation rel;
  334. HeapScanDesc scan;
  335. HeapTuple tup;
  336. if (strlen(relname) >= NAMEDATALEN - 1)
  337. relname[NAMEDATALEN - 1] = '';
  338. if (Typ == (struct typmap **) NULL)
  339. {
  340. StartPortalAllocMode(DefaultAllocMode, 0);
  341. rel = heap_openr(TypeRelationName);
  342. scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
  343. i = 0;
  344. while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
  345. ++i;
  346. heap_endscan(scan);
  347. app = Typ = ALLOC(struct typmap *, i + 1);
  348. while (i-- > 0)
  349. *app++ = ALLOC(struct typmap, 1);
  350. *app = (struct typmap *) NULL;
  351. scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
  352. app = Typ;
  353. while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
  354. {
  355. (*app)->am_oid = tup->t_data->t_oid;
  356. memmove((char *) &(*app++)->am_typ,
  357. (char *) GETSTRUCT(tup),
  358. sizeof((*app)->am_typ));
  359. }
  360. heap_endscan(scan);
  361. heap_close(rel);
  362. EndPortalAllocMode();
  363. }
  364. if (reldesc != NULL)
  365. closerel(NULL);
  366. if (!Quiet)
  367. printf("Amopen: relation %s. attrsize %dn", relname ? relname : "(null)",
  368.    (int) ATTRIBUTE_TUPLE_SIZE);
  369. reldesc = heap_openr(relname);
  370. Assert(reldesc);
  371. numattr = reldesc->rd_rel->relnatts;
  372. for (i = 0; i < numattr; i++)
  373. {
  374. if (attrtypes[i] == NULL)
  375. attrtypes[i] = AllocateAttribute();
  376. memmove((char *) attrtypes[i],
  377. (char *) reldesc->rd_att->attrs[i],
  378. ATTRIBUTE_TUPLE_SIZE);
  379. /* Some old pg_attribute tuples might not have attisset. */
  380. /*
  381.  * If the attname is attisset, don't look for it - it may not be
  382.  * defined yet.
  383.  */
  384. if (namestrcmp(&attrtypes[i]->attname, "attisset") == 0)
  385. attrtypes[i]->attisset = get_attisset(RelationGetRelid(reldesc),
  386.  attrtypes[i]->attname.data);
  387. else
  388. attrtypes[i]->attisset = false;
  389. if (DebugMode)
  390. {
  391. Form_pg_attribute at = attrtypes[i];
  392. printf("create attribute %d name %s len %d num %d type %dn",
  393.    i, at->attname.data, at->attlen, at->attnum,
  394.    at->atttypid
  395. );
  396. fflush(stdout);
  397. }
  398. }
  399. }
  400. /* ----------------
  401.  * closerel
  402.  * ----------------
  403.  */
  404. void
  405. closerel(char *name)
  406. {
  407. if (name)
  408. {
  409. if (reldesc)
  410. {
  411. if (namestrcmp(RelationGetRelationName(reldesc), name) != 0)
  412. elog(ERROR, "closerel: close of '%s' when '%s' was expected",
  413.  name, relname ? relname : "(null)");
  414. }
  415. else
  416. elog(ERROR, "closerel: close of '%s' before any relation was opened",
  417.  name);
  418. }
  419. if (reldesc == NULL)
  420. elog(ERROR, "Warning: no opened relation to close.n");
  421. else
  422. {
  423. if (!Quiet)
  424. printf("Amclose: relation %s.n", relname ? relname : "(null)");
  425. heap_close(reldesc);
  426. reldesc = (Relation) NULL;
  427. }
  428. }
  429. /* ----------------
  430.  * DEFINEATTR()
  431.  *
  432.  * define a <field,type> pair
  433.  * if there are n fields in a relation to be created, this routine
  434.  * will be called n times
  435.  * ----------------
  436.  */
  437. void
  438. DefineAttr(char *name, char *type, int attnum)
  439. {
  440. int attlen;
  441. Oid typeoid;
  442. if (reldesc != NULL)
  443. {
  444. fputs("Warning: no open relations allowed with 't' command.n", stderr);
  445. closerel(relname);
  446. }
  447. typeoid = gettype(type);
  448. if (attrtypes[attnum] == (Form_pg_attribute) NULL)
  449. attrtypes[attnum] = AllocateAttribute();
  450. if (Typ != (struct typmap **) NULL)
  451. {
  452. attrtypes[attnum]->atttypid = Ap->am_oid;
  453. namestrcpy(&attrtypes[attnum]->attname, name);
  454. if (!Quiet)
  455. printf("<%s %s> ", attrtypes[attnum]->attname.data, type);
  456. attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
  457. attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen;
  458. attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
  459. attrtypes[attnum]->attalign = Ap->am_typ.typalign;
  460. }
  461. else
  462. {
  463. attrtypes[attnum]->atttypid = Procid[typeoid].oid;
  464. namestrcpy(&attrtypes[attnum]->attname, name);
  465. if (!Quiet)
  466. printf("<%s %s> ", attrtypes[attnum]->attname.data, type);
  467. attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
  468. attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
  469. /*
  470.  * Cheat like mad to fill in these items from the length only.
  471.  * This only has to work for types used in the system catalogs...
  472.  */
  473. switch (attlen)
  474. {
  475. case 1:
  476. attrtypes[attnum]->attbyval = true;
  477. attrtypes[attnum]->attalign = 'c';
  478. break;
  479. case 2:
  480. attrtypes[attnum]->attbyval = true;
  481. attrtypes[attnum]->attalign = 's';
  482. break;
  483. case 4:
  484. attrtypes[attnum]->attbyval = true;
  485. attrtypes[attnum]->attalign = 'i';
  486. break;
  487. default:
  488. attrtypes[attnum]->attbyval = false;
  489. attrtypes[attnum]->attalign = 'i';
  490. break;
  491. }
  492. }
  493. attrtypes[attnum]->attcacheoff = -1;
  494. attrtypes[attnum]->atttypmod = -1;
  495. }
  496. /* ----------------
  497.  * InsertOneTuple
  498.  * assumes that 'oid' will not be zero.
  499.  * ----------------
  500.  */
  501. void
  502. InsertOneTuple(Oid objectid)
  503. {
  504. HeapTuple tuple;
  505. TupleDesc tupDesc;
  506. int i;
  507. if (DebugMode)
  508. {
  509. printf("InsertOneTuple oid %u, %d attrsn", objectid, numattr);
  510. fflush(stdout);
  511. }
  512. tupDesc = CreateTupleDesc(numattr, attrtypes);
  513. tuple = heap_formtuple(tupDesc, (Datum *) values, Blanks);
  514. pfree(tupDesc); /* just free's tupDesc, not the attrtypes */
  515. if (objectid != (Oid) 0)
  516. tuple->t_data->t_oid = objectid;
  517. heap_insert(reldesc, tuple);
  518. pfree(tuple);
  519. if (DebugMode)
  520. {
  521. printf("End InsertOneTuple, objectid=%un", objectid);
  522. fflush(stdout);
  523. }
  524. /*
  525.  * Reset blanks for next tuple
  526.  */
  527. for (i = 0; i < numattr; i++)
  528. Blanks[i] = ' ';
  529. }
  530. /* ----------------
  531.  * InsertOneValue
  532.  * ----------------
  533.  */
  534. void
  535. InsertOneValue(Oid objectid, char *value, int i)
  536. {
  537. int typeindex;
  538. char    *prt;
  539. struct typmap **app;
  540. if (DebugMode)
  541. printf("Inserting value: '%s'n", value);
  542. if (i < 0 || i >= MAXATTR)
  543. {
  544. printf("i out of range: %dn", i);
  545. Assert(0);
  546. }
  547. if (Typ != (struct typmap **) NULL)
  548. {
  549. struct typmap *ap;
  550. if (DebugMode)
  551. puts("Typ != NULL");
  552. app = Typ;
  553. while (*app && (*app)->am_oid != reldesc->rd_att->attrs[i]->atttypid)
  554. ++app;
  555. ap = *app;
  556. if (ap == NULL)
  557. {
  558. printf("Unable to find atttypid in Typ list! %un",
  559.    reldesc->rd_att->attrs[i]->atttypid
  560. );
  561. Assert(0);
  562. }
  563. values[i] = fmgr(ap->am_typ.typinput,
  564.  value,
  565.  ap->am_typ.typelem,
  566.  -1); /* shouldn't have char() or varchar()
  567.  * types during boostrapping but just to
  568.  * be safe */
  569. prt = fmgr(ap->am_typ.typoutput, values[i],
  570.    ap->am_typ.typelem);
  571. if (!Quiet)
  572. printf("%s ", prt);
  573. pfree(prt);
  574. }
  575. else
  576. {
  577. typeindex = attrtypes[i]->atttypid - FIRST_TYPE_OID;
  578. if (DebugMode)
  579. printf("Typ == NULL, typeindex = %u idx = %dn", typeindex, i);
  580. values[i] = fmgr(Procid[typeindex].inproc, value,
  581.  Procid[typeindex].elem, -1);
  582. prt = fmgr(Procid[typeindex].outproc, values[i],
  583.    Procid[typeindex].elem);
  584. if (!Quiet)
  585. printf("%s ", prt);
  586. pfree(prt);
  587. }
  588. if (DebugMode)
  589. {
  590. puts("End InsertValue");
  591. fflush(stdout);
  592. }
  593. }
  594. /* ----------------
  595.  * InsertOneNull
  596.  * ----------------
  597.  */
  598. void
  599. InsertOneNull(int i)
  600. {
  601. if (DebugMode)
  602. printf("Inserting nulln");
  603. if (i < 0 || i >= MAXATTR)
  604. elog(FATAL, "i out of range (too many attrs): %dn", i);
  605. values[i] = (char *) NULL;
  606. Blanks[i] = 'n';
  607. }
  608. #define MORE_THAN_THE_NUMBER_OF_CATALOGS 256
  609. static bool
  610. BootstrapAlreadySeen(Oid id)
  611. {
  612. static Oid seenArray[MORE_THAN_THE_NUMBER_OF_CATALOGS];
  613. static int nseen = 0;
  614. bool seenthis;
  615. int i;
  616. seenthis = false;
  617. for (i = 0; i < nseen; i++)
  618. {
  619. if (seenArray[i] == id)
  620. {
  621. seenthis = true;
  622. break;
  623. }
  624. }
  625. if (!seenthis)
  626. {
  627. seenArray[nseen] = id;
  628. nseen++;
  629. }
  630. return seenthis;
  631. }
  632. /* ----------------
  633.  * cleanup
  634.  * ----------------
  635.  */
  636. static void
  637. cleanup()
  638. {
  639. static int beenhere = 0;
  640. if (!beenhere)
  641. beenhere = 1;
  642. else
  643. {
  644. elog(FATAL, "Memory manager fault: cleanup called twice.n", stderr);
  645. proc_exit(1);
  646. }
  647. if (reldesc != (Relation) NULL)
  648. heap_close(reldesc);
  649. CommitTransactionCommand();
  650. proc_exit(Warnings);
  651. }
  652. /* ----------------
  653.  * gettype
  654.  * ----------------
  655.  */
  656. static Oid
  657. gettype(char *type)
  658. {
  659. int i;
  660. Relation rel;
  661. HeapScanDesc scan;
  662. HeapTuple tup;
  663. struct typmap **app;
  664. if (Typ != (struct typmap **) NULL)
  665. {
  666. for (app = Typ; *app != (struct typmap *) NULL; app++)
  667. {
  668. if (strncmp((*app)->am_typ.typname.data, type, NAMEDATALEN) == 0)
  669. {
  670. Ap = *app;
  671. return (*app)->am_oid;
  672. }
  673. }
  674. }
  675. else
  676. {
  677. for (i = 0; i <= n_types; i++)
  678. {
  679. if (strncmp(type, Procid[i].name, NAMEDATALEN) == 0)
  680. return i;
  681. }
  682. if (DebugMode)
  683. printf("bootstrap.c: External Type: %sn", type);
  684. rel = heap_openr(TypeRelationName);
  685. scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
  686. i = 0;
  687. while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
  688. ++i;
  689. heap_endscan(scan);
  690. app = Typ = ALLOC(struct typmap *, i + 1);
  691. while (i-- > 0)
  692. *app++ = ALLOC(struct typmap, 1);
  693. *app = (struct typmap *) NULL;
  694. scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
  695. app = Typ;
  696. while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
  697. {
  698. (*app)->am_oid = tup->t_data->t_oid;
  699. memmove((char *) &(*app++)->am_typ,
  700. (char *) GETSTRUCT(tup),
  701. sizeof((*app)->am_typ));
  702. }
  703. heap_endscan(scan);
  704. heap_close(rel);
  705. return gettype(type);
  706. }
  707. elog(ERROR, "Error: unknown type '%s'.n", type);
  708. err_out();
  709. /* not reached, here to make compiler happy */
  710. return 0;
  711. }
  712. /* ----------------
  713.  * AllocateAttribute
  714.  * ----------------
  715.  */
  716. static Form_pg_attribute /* XXX */
  717. AllocateAttribute()
  718. {
  719. Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_TUPLE_SIZE);
  720. if (!PointerIsValid(attribute))
  721. elog(FATAL, "AllocateAttribute: malloc failed");
  722. MemSet(attribute, 0, ATTRIBUTE_TUPLE_SIZE);
  723. return attribute;
  724. }
  725. /* ----------------
  726.  * MapArrayTypeName
  727.  * XXX arrays of "basetype" are always "_basetype".
  728.  *    this is an evil hack inherited from rel. 3.1.
  729.  * XXX array dimension is thrown away because we
  730.  *    don't support fixed-dimension arrays.  again,
  731.  *    sickness from 3.1.
  732.  *
  733.  * the string passed in must have a '[' character in it
  734.  *
  735.  * the string returned is a pointer to static storage and should NOT
  736.  * be freed by the CALLER.
  737.  * ----------------
  738.  */
  739. char *
  740. MapArrayTypeName(char *s)
  741. {
  742. int i,
  743. j;
  744. static char newStr[NAMEDATALEN]; /* array type names < NAMEDATALEN
  745.  * long */
  746. if (s == NULL || s[0] == '')
  747. return s;
  748. j = 1;
  749. newStr[0] = '_';
  750. for (i = 0; i < NAMEDATALEN - 1 && s[i] != '['; i++, j++)
  751. newStr[j] = s[i];
  752. newStr[j] = '';
  753. return newStr;
  754. }
  755. /* ----------------
  756.  * EnterString
  757.  * returns the string table position of the identifier
  758.  * passed to it.  We add it to the table if we can't find it.
  759.  * ----------------
  760.  */
  761. int
  762. EnterString(char *str)
  763. {
  764. hashnode   *node;
  765. int len;
  766. len = strlen(str);
  767. node = FindStr(str, len, 0);
  768. if (node)
  769. return node->strnum;
  770. else
  771. {
  772. node = AddStr(str, len, 0);
  773. return node->strnum;
  774. }
  775. }
  776. /* ----------------
  777.  * LexIDStr
  778.  * when given an idnum into the 'string-table' return the string
  779.  * associated with the idnum
  780.  * ----------------
  781.  */
  782. char *
  783. LexIDStr(int ident_num)
  784. {
  785. return strtable[ident_num];
  786. }
  787. /* ----------------
  788.  * CompHash
  789.  *
  790.  * Compute a hash function for a given string.  We look at the first,
  791.  * the last, and the middle character of a string to try to get spread
  792.  * the strings out.  The function is rather arbitrary, except that we
  793.  * are mod'ing by a prime number.
  794.  * ----------------
  795.  */
  796. static int
  797. CompHash(char *str, int len)
  798. {
  799. int result;
  800. result = (NUM * str[0] + NUMSQR * str[len - 1] + NUMCUBE * str[(len - 1) / 2]);
  801. return result % HASHTABLESIZE;
  802. }
  803. /* ----------------
  804.  * FindStr
  805.  *
  806.  * This routine looks for the specified string in the hash
  807.  * table. It returns a pointer to the hash node found,
  808.  * or NULL if the string is not in the table.
  809.  * ----------------
  810.  */
  811. static hashnode *
  812. FindStr(char *str, int length, hashnode *mderef)
  813. {
  814. hashnode   *node;
  815. node = hashtable[CompHash(str, length)];
  816. while (node != NULL)
  817. {
  818. /*
  819.  * We must differentiate between string constants that might have
  820.  * the same value as a identifier and the identifier itself.
  821.  */
  822. if (!strcmp(str, strtable[node->strnum]))
  823. {
  824. return node; /* no need to check */
  825. }
  826. else
  827. node = node->next;
  828. }
  829. /* Couldn't find it in the list */
  830. return NULL;
  831. }
  832. /* ----------------
  833.  * AddStr
  834.  *
  835.  * This function adds the specified string, along with its associated
  836.  * data, to the hash table and the string table.  We return the node
  837.  * so that the calling routine can find out the unique id that AddStr
  838.  * has assigned to this string.
  839.  * ----------------
  840.  */
  841. static hashnode *
  842. AddStr(char *str, int strlength, int mderef)
  843. {
  844. hashnode   *temp,
  845.    *trail,
  846.    *newnode;
  847. int hashresult;
  848. int len;
  849. if (++strtable_end == STRTABLESIZE)
  850. {
  851. /* Error, string table overflow, so we Punt */
  852. elog(FATAL,
  853.  "There are too many string constants and identifiers for the compiler to handle.");
  854. }
  855. /*
  856.  * Some of the utilites (eg, define type, create relation) assume that
  857.  * the string they're passed is a NAMEDATALEN.  We get array bound
  858.  * read violations from purify if we don't allocate at least
  859.  * NAMEDATALEN bytes for strings of this sort. Because we're lazy, we
  860.  * allocate at least NAMEDATALEN bytes all the time.
  861.  */
  862. if ((len = strlength + 1) < NAMEDATALEN)
  863. len = NAMEDATALEN;
  864. strtable[strtable_end] = malloc((unsigned) len);
  865. strcpy(strtable[strtable_end], str);
  866. /* Now put a node in the hash table */
  867. newnode = (hashnode *) malloc(sizeof(hashnode) * 1);
  868. newnode->strnum = strtable_end;
  869. newnode->next = NULL;
  870. /* Find out where it goes */
  871. hashresult = CompHash(str, strlength);
  872. if (hashtable[hashresult] == NULL)
  873. hashtable[hashresult] = newnode;
  874. else
  875. { /* There is something in the list */
  876. trail = hashtable[hashresult];
  877. temp = trail->next;
  878. while (temp != NULL)
  879. {
  880. trail = temp;
  881. temp = temp->next;
  882. }
  883. trail->next = newnode;
  884. }
  885. return newnode;
  886. }
  887. /*
  888.  * index_register() -- record an index that has been set up for building
  889.  * later.
  890.  *
  891.  * At bootstrap time, we define a bunch of indices on system catalogs.
  892.  * We postpone actually building the indices until just before we're
  893.  * finished with initialization, however. This is because more classes
  894.  * and indices may be defined, and we want to be sure that all of them
  895.  * are present in the index.
  896.  */
  897. void
  898. index_register(char *heap,
  899.    char *ind,
  900.    int natts,
  901.    AttrNumber *attnos,
  902.    uint16 nparams,
  903.    Datum *params,
  904.    FuncIndexInfo *finfo,
  905.    PredInfo *predInfo)
  906. {
  907. Datum    *v;
  908. IndexList  *newind;
  909. int len;
  910. MemoryContext oldcxt;
  911. /*
  912.  * XXX mao 10/31/92 -- don't gc index reldescs, associated info at
  913.  * bootstrap time. we'll declare the indices now, but want to create
  914.  * them later.
  915.  */
  916. if (nogc == (GlobalMemory) NULL)
  917. nogc = CreateGlobalMemory("BootstrapNoGC");
  918. oldcxt = MemoryContextSwitchTo((MemoryContext) nogc);
  919. newind = (IndexList *) palloc(sizeof(IndexList));
  920. newind->il_heap = pstrdup(heap);
  921. newind->il_ind = pstrdup(ind);
  922. newind->il_natts = natts;
  923. if (PointerIsValid(finfo))
  924. len = FIgetnArgs(finfo) * sizeof(AttrNumber);
  925. else
  926. len = natts * sizeof(AttrNumber);
  927. newind->il_attnos = (AttrNumber *) palloc(len);
  928. memmove(newind->il_attnos, attnos, len);
  929. if ((newind->il_nparams = nparams) > 0)
  930. {
  931. v = newind->il_params = (Datum *) palloc(2 * nparams * sizeof(Datum));
  932. nparams *= 2;
  933. while (nparams-- > 0)
  934. {
  935. *v = (Datum) palloc(strlen((char *) (*params)) + 1);
  936. strcpy((char *) *v++, (char *) *params++);
  937. }
  938. }
  939. else
  940. newind->il_params = (Datum *) NULL;
  941. if (finfo != (FuncIndexInfo *) NULL)
  942. {
  943. newind->il_finfo = (FuncIndexInfo *) palloc(sizeof(FuncIndexInfo));
  944. memmove(newind->il_finfo, finfo, sizeof(FuncIndexInfo));
  945. }
  946. else
  947. newind->il_finfo = (FuncIndexInfo *) NULL;
  948. if (predInfo != NULL)
  949. {
  950. newind->il_predInfo = (PredInfo *) palloc(sizeof(PredInfo));
  951. newind->il_predInfo->pred = predInfo->pred;
  952. newind->il_predInfo->oldPred = predInfo->oldPred;
  953. }
  954. else
  955. newind->il_predInfo = NULL;
  956. newind->il_next = ILHead;
  957. ILHead = newind;
  958. MemoryContextSwitchTo(oldcxt);
  959. }
  960. void
  961. build_indices()
  962. {
  963. Relation heap;
  964. Relation ind;
  965. for (; ILHead != (IndexList *) NULL; ILHead = ILHead->il_next)
  966. {
  967. heap = heap_openr(ILHead->il_heap);
  968. ind = index_openr(ILHead->il_ind);
  969. index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos,
  970.  ILHead->il_nparams, ILHead->il_params, ILHead->il_finfo,
  971. ILHead->il_predInfo);
  972. /*
  973.  * All of the rest of this routine is needed only because in
  974.  * bootstrap processing we don't increment xact id's.  The normal
  975.  * DefineIndex code replaces a pg_class tuple with updated info
  976.  * including the relhasindex flag (which we need to have updated).
  977.  * Unfortunately, there are always two indices defined on each
  978.  * catalog causing us to update the same pg_class tuple twice for
  979.  * each catalog getting an index during bootstrap resulting in the
  980.  * ghost tuple problem (see heap_replace). To get around this we
  981.  * change the relhasindex field ourselves in this routine keeping
  982.  * track of what catalogs we already changed so that we don't
  983.  * modify those tuples twice.  The normal mechanism for updating
  984.  * pg_class is disabled during bootstrap.
  985.  *
  986.  * -mer
  987.  */
  988. heap = heap_openr(ILHead->il_heap);
  989. if (!BootstrapAlreadySeen(RelationGetRelid(heap)))
  990. UpdateStats(RelationGetRelid(heap), 0, true);
  991. }
  992. }