home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre2.z / postgre2 / doc / developer / architecture.m
Encoding:
Text File  |  1992-08-27  |  20.5 KB  |  567 lines

  1. .sh 1 "Postgres Architecture and Historical Lore"
  2. .pp
  3. .sh 1 "Introduction"
  4. .pp
  5. In the beginning, there was Ingres.  And then, after ways to improve the
  6. relational model made themselves known, and as ways to implement
  7. object-oriented
  8. techniques of data organization without completely throwing out time-honored
  9. ways of doing things became necessary, Postgres came into being.
  10. .pp
  11. The original release of Postgres was partially written in Franz Lisp and
  12. partially written in C.  However, this proved to be a rather difficult
  13. environment in which to work and debug, and was quite a problem for any
  14. potential users - it was painfully slow, and required expensive third-party
  15. licenses for the Lisp environment.  Because of this, Postgres was ported to C,
  16. and the first C-only release went out in late 1988.
  17. .pp
  18. Subsequent releases of the Postgres software have stressed improvements and
  19. complete rewrites of various features including the Postgres rule system,
  20. the transaction system, the executor, access methods, as well as several 
  21. ports to different machines.
  22. .pp
  23. In the following discussions, a general overview of the internal structure
  24. of Postgres will be presented, together with references to directories where
  25. these structures may be found.  This is intended to be a rather quick "tour"
  26. of the Postgres code, stressing general principles and ideas rather than
  27. details such as function names.  For that level of detail, the code itself is
  28. the best (and only) reference.  It must be admitted here that precision is
  29. being avoided as much to keep this document from rapidly getting out of date as
  30. much as anything else.
  31. .pp
  32. .sh 1 "General overview of Postgres at the communication level"
  33. .pp
  34. The three main programs in the Postgres environment are the following:
  35. .pp
  36. .(l
  37. User Applications
  38. The "postmaster"
  39. The Postgres backend
  40. .)l
  41. .sh 2 "User Applications"
  42. .pp
  43. A User Application is any program that uses LIBPQ to send and recieve data from
  44. a Postgres backend.  A User Application can run on any host that can access the
  45. Postgres server from a TCP-IP network.  User applications included in the
  46. Postgres distribution include the terminal monitor (monitor), the database
  47. creation program (createdb), and the database deletion program (destroydb).
  48. .pp
  49. .sh 2 "The postmaster"
  50. .pp
  51. The Postmaster handles most of the network initialization and connection
  52. activities.  Once the Postmaster has handled the network stuff for a user
  53. application, it forks off a Postgres backend.  Once this is done, the
  54. Postmaster is no longer involved, and goes back to waiting for connections
  55. from new user applications.
  56. .pp
  57. The first time the Postmaster is invoked, it allocates shared memory and
  58. semaphores used by Postgres backends for locking and buffer pools.
  59. .pp
  60. The postmaster and the backend have to run on the database server, and the
  61. database directories should be on local disks.
  62. .pp
  63. .sh 2 "The Postgres backend"
  64. .pp
  65. The Postgres backend is the true database engine.  Once it has been forked by
  66. a postmaster, it is ready to recieve queries from and send back answers to the
  67. user application.
  68. .pp
  69. For every user application, there is one Postgres backend forked by the
  70. Postmaster.  
  71. .pp
  72. .sh 1 "Overview of the Postgres Main Modules"
  73. .pp
  74. In this section, the general program flow in Postgres will be discussed, with
  75. a brief description of each program module, together with instructions on
  76. where to find the source code for that module.  All modules discussed here
  77. are part of the Postgres backend, and are relatively tightly coupled at this
  78. time.  The Postgres main modules include:
  79. .pp
  80. .(l
  81. o  The Parser
  82. o  The Query Rewrite Rule System
  83. o  The Planner/Optimizer
  84. o  The Executor
  85. o  The Instance Level Rule System
  86. o  The Access Methods
  87. o  Housekeeping functions 
  88. o  Lock managers, cache utilities, and other miscellaneous functions.
  89. .)l
  90. .pp
  91. In the execution of a Retrieve query, the following general flow is followed.
  92. Appends and other queries that access data (as opposed to "housekeeping" queries
  93. such as createdb, copy, etc) follow a similar flow.
  94. .pp
  95. .l(
  96.                  ----------------
  97.                  |  1.  Parser  |
  98.                  ----------------
  99.                         |
  100.                         | (Initial Query Parse Tree)
  101.                         |
  102.                         v
  103.           +-------------------------------+
  104.           | 2.  Query Rewrite Rule System |
  105.           +-------------------------------+
  106.                         |
  107.                         | (Re-written Query Parse Tree)
  108.                         |
  109.                         |
  110.                         v
  111.               +-----------------------+
  112.               | 3.  Planner/Optimizer |
  113.               +-----------------------+
  114.                         |
  115.                         | (Execution Plan Tree)
  116.                         |
  117.                         v
  118.                 +------------------+
  119.                 | 4.  Executor     |
  120.                 +------------------+
  121.                         |
  122.                         | (Open request)
  123.                         |
  124.                         |
  125.                         |          (get instances until done)
  126.                         v                    
  127.                  +-------------------+              +-----------------+
  128.                  | 5. Access Methods |<-------------| 4.  Executor    |
  129.                  +-------------------+              +-----------------+
  130.                         |                                  ^
  131.                         | (instance)                       |
  132.                         |                                  | (instance)
  133.                         v                                  |
  134.                  +-------------------------------+         |
  135.                  | 6. Instance Level Rule System |---------+
  136.                  +-------------------------------+
  137. .)l
  138. .sh 2 "The Parser"
  139. .pp
  140. The Parser parses a Postquel query and generates a parse-tree.  As long as
  141. a correct parse-tree is generated, other parsers for other query languages
  142. (ie SQL) can be "dropped in" to the Postgres system.  The Postquel query
  143. parser lives in:
  144. .pp
  145. .(l
  146. ~/src/parser
  147. .)l
  148. .pp
  149. .sh 2 "The Query Rewrite rule system"
  150. .pp
  151. The Query Rewrite rule system is essentially part of the parser.  It generally
  152. works in the following manner:  If there is a query-rewrite rule on this
  153. class of instances, add the rule to the initial user query through the use of
  154. boolean algebra.  If not, just let the query go through.
  155. .pp
  156. The Query Rewrite rule system is used to implement not only obvious rules, but
  157. also versions, views, and postquel procedures.  The Query Rewrite system
  158. lives in:
  159. .pp
  160. .(l
  161. ~/src/rewrite
  162. .)l
  163. .sh 2 "The Planner/Optimizer"
  164. .pp
  165. The Planner/Optimizer takes a parse-tree and, using various cost functions and
  166. heuristics, generates an execution plan.  The Planner/Optimizer also "drives"
  167. the executor in that it calls it once to initialize things and then calls it
  168. subsequently to fetch instances.  The planner lives in:
  169. .pp
  170. .(l
  171. ~/src/planner
  172. .)l
  173. .pp
  174. .sh 2 "The Executor"
  175. .pp
  176. The first time the Executor is invoked by the Planner, it initializes itself,
  177. the access methods, and the instance-level rule system.  In subsequent calls by
  178. the Planner, it walks the execution plan, fetching instances by calling the
  179. access methods and checking them against the query qualification (which is
  180. part of the execution plan) to see if they are part of the "answer" to the user
  181. query.  Before doing this, however, it checks to see if a fetched instance
  182. triggers a instance-level rule.  The Executor lives in:
  183. .pp
  184. .(l
  185. ~/src/executor
  186. .)l
  187. .pp
  188. .sh 2 "The Access Methods"
  189. .pp
  190. These are the low-level routines that hit the disk and handle any indices (ie
  191. btrees, rtrees) that the user may have defined.  The Heap access method is
  192. used as the primary access method, and other access methods are defined on
  193. indices.  The Executor calls these
  194. routines to fetch instances - the Access Methods then use a scanning mechanism
  195. defined by the Planner to get them and fetch them back to the executor.  The
  196. Access Methods primarily live in:
  197. .pp
  198. .(l
  199. ~/src/access/common       (Code used by all access methods)
  200. ~/src/access/heap         (Heap access method - the lowest level)
  201.  
  202. ~/src/access/{index index-btree index-ftree index-rtree}
  203.                           (Code to handle indices, and 
  204.                            Various different types of indices)
  205.  
  206. ~/src/access/transam      (The Postgres Transaction System)
  207. .)l
  208. .sh 2 "The Instance-level Rule System"
  209. .pp
  210. The Instance-level rule system operates in the following manner:  in the
  211. "system data" part of each instance, there is a field for instance level
  212. "rule locks".  If a fetched instance has a rule lock, the associated rule(s)
  213. is executed.  Each instance-level rule has an associated execution plan, so
  214. the executor will be
  215. ran from within the instance-level rule system.  The modified instance, if any,
  216. is then handed back to the executor for further processing.  The Instance-level
  217. Rule System lives in:
  218. .pp
  219. .(l
  220. ~/src/rules/prs2 (Postgres Rule System 2 - the bulk of the rule system)
  221. ~/src/rules/stubs
  222. .)l
  223. .sh 2 "Housekeeping Functions"
  224. .pp
  225. For queries that are not directly related to retrieving or appending, such
  226. as creating databases, defining new operators, rules, and registering user
  227. functions, the parser simply bypasses the planner and executor and directly
  228. calls utility routines to handle these special commands.  The code for these
  229. routines is in:
  230. .pp
  231. .(l
  232. ~/src/commands
  233. .)l
  234. .pp
  235. .sh 2 "Lock managers, cache utilities, and other miscellaneous functions"
  236. .pp
  237. There are numerous other functions that are used in Postgres; these include
  238. functions to manage system attributes, lock managers, buffer and cache
  239. managers, hash table handlers, as well as the system built-in functions for
  240. pre-defined types.  For lack of anything better to call these, these live in
  241. the UTIL module, and live in:
  242. .pp
  243. .(l
  244. ~/src/utils/adt   (built-in functions)
  245. ~/src/utils/cache (cache handlers)
  246. ~/src/utils/error (error handlers)
  247. ~/src/utils/fmgr  (the "Function Manager" - handles ADT's and user functions)
  248. ~/src/utils/hash  (hash table handlers)
  249. ~/src/utils/init  (initialization code)
  250. ~/src/utils/mmgr  (memory manager code)
  251. ~/src/utils/sort  (sort code)
  252. ~/src/utils/time  (time range qualification handlers)
  253. .)l
  254. .pp
  255. .sh 2 "'Main' Programs"
  256. .pp
  257. The "main programs" for the Postgres backend, the Postmaster, and other
  258. utilities like the vacuum daemon, etc live in
  259. .pp
  260. .(l
  261. ~/src/support (everything but the backend)
  262. ~/src/tcop    (the backend main program - in postgres.c)
  263. .)l
  264. .pp
  265. .sh 1 "Postgres internal data structures"
  266. .pp
  267. Since Postgres was originally written in Lisp, and for a time was a Lisp-C
  268. hybrid, many of its internal data structures are rather opaque to the C
  269. programmer.  However, they are not overly difficult to understand and use once
  270. the basic ideas behind them are made clear.  The discussion in this section
  271. will attempt to make these ideas clear, without dwelling excessively on
  272. details and trivia.
  273. .pp
  274. .sh 2 "The CONS-cell abstraction"
  275. .pp
  276. Internally, Postgres passes data about primarily in trees made of Lisp-like
  277. CONS-cell structures.  These CONS-cells can point to interesting data only,
  278. to interesting data and another CONS-cell, or to two other CONS-cells.  In
  279. particualar, parse-trees and execution plans are encoded in these CONS-cell
  280. structures.  Utility functions for handling the Lisp-like structures are in
  281. .pp
  282. .(l
  283. ~/src/lib/C
  284. .)l
  285. .sh 2 "The Postgres Node System"
  286. .pp
  287. A collection of data structures that is central to most Postgres operations
  288. is the Postgres "node system".  This is a collection of data structures that
  289. encode various directives for the executor and planner, as well as numerous
  290. other "utility" purposes.  Nodes are declared using a C++-like syntax that
  291. is used by a shell script to generate initialization and accessor functions.
  292. C preprocessor magic is used to ultimately turn this declaration into an
  293. ordinary C typedef.
  294. .pp
  295. .sh 3 "An Example Node"
  296. .pp
  297. An example of a Postgres node is the following:
  298. .pp
  299. .(l
  300. class (Oper) public (Expr) {
  301. /* private: */
  302.     inherits(Expr);
  303.     InstanceId            opno;
  304.     InstanceId            opid;
  305.     bool                oprelationlevel;
  306.     InstanceId            opresulttype;
  307.     int                 opsize;
  308.     FunctionCachePtr    op_fcache;
  309. /* public: */
  310. };
  311.  
  312. (this particular node is from ~/src/lib/H/nodes/primnodes.h)
  313.  
  314. .)l
  315. .pp
  316. This particular node is used in execution plans to indicate that an operator
  317. must be executed.  The "inherits" macro is used to inherit fields from the
  318. previously defined Expr (expression) node, and the explicit fields are fields
  319. that are unique to the Oper node itself.  Declarations for all Postgres nodes
  320. are in header files in
  321. .pp
  322. .(l
  323. ~/src/lib/H/nodes
  324. .)l
  325. .pp
  326. As stated earlier, shell scripts read the node declarations and generate
  327. initializer and accessor functions for them.  As long as the above declaration
  328. scheme is used, these scripts will work for new nodes as well.  These scripts
  329. are in
  330. .pp
  331. .(l
  332. ~/src/lib/Gen
  333. .)l
  334. .sh 3 "Usage of the Node System"
  335. .pp
  336. The different nodes are primarily used to give directives to the Executor in
  337. the execution plan.  Nodes are used to indicate the scan type to be used,
  338. whether sorting is to be used or not, and are used to indicate how query
  339. qualifications are to be handled.  
  340. .pp
  341. .sh 3 "Printing Nodes and Node Structures"
  342. .pp
  343. The best place to figure out what a structure using nodes and CONS-cells
  344. is like is to look carefully at the code in 
  345. .pp
  346. .(l
  347. ~/src/lib/C
  348. .)l
  349. .pp
  350. The code in this directory prints node structures into strings and dumps them
  351. into strings.  This code is primarily used by the Instance Level Rule System to
  352. save and restore execution plans that are associated with rules, which it
  353. stores on disk in a system class in string format.  The function
  354. .pp
  355. .(l
  356. LispDisplay(CONS-cell, 0)
  357. .)l
  358. .pp
  359. displays the contents of a CONS-cell structure in a human readable but rather
  360. unfriendly format.
  361. .pp
  362. .sh 2 "Other Important Data Structures"
  363. .pp
  364. Aside from the CONS-cell and Node structures, there are very few other
  365. important global data structures, although there are numerous local structures
  366. that are important if one is modifying variosu functions.  One exception is
  367. the HeapTuple data structure and its associated structures, since it is the
  368. type returned by virtually all the access methods, including those that handle
  369. system classes.  The declaration for the HeapTuple type is in
  370. .pp
  371. .(l
  372. ~/src/access/htup.h
  373. .)l
  374. .pp
  375. .sh 1 "The Postgres Function Manager"
  376. .pp
  377. An integral part of Postgres is its ability to use user-defined functions and
  378. operators.  The Postgres Function Manager is responsible for handling this
  379. aspect of Postgres.
  380. .pp
  381. .sh 2 "The Function Manager"
  382. .pp
  383. The Function Manager is used by all parts of Postgres that examine the
  384. internals of user data.  It consists of several parts:
  385. .pp
  386. .(l
  387. o  The Function Manager Interface
  388. o  Data structures containing information about dynamically loaded files
  389. o  The dynamic loader
  390. .)l
  391. .pp
  392. .sh 3 "The Function Manager Interface"
  393. .pp
  394. The basic reason for the existance of the Function Manager is that due to
  395. the nature of user-defined functions, calls to them cannot be hardcoded anywere
  396. in the Postgres backend.  A mechanism must exist which obtains addresses of
  397. user-defined and builtin functions (there is very little difference between
  398. these), handles the task of calling user-defined functions with appropriate
  399. arguments, and returning an appropriate value.  The Function Manager Interface
  400. provides the abstraction from the details of calling user-defined functions
  401. from the rest of Postgres.  The source to the Function Manager Interface is in 
  402. .pp
  403. .(l
  404. ~/src/utils/fmgr/fmgr.c
  405. .)l
  406. .pp
  407. .sh 3 "Data Structures used for Function Execution"
  408. .pp
  409. In the Function Manager, there are two in-memory data structures used for
  410. looking up function addresses.  One is an array of builtin functions that
  411. is sorted by function OID.  Another is a list of dynamically loaded files,
  412. which contains the addresses of each function in these files.  Functions that
  413. populate and access these data structures are in
  414. .pp
  415. .(l
  416. ~/src/utils/fmgr/dfmgr.c
  417. ~/src/port/*/dynloader.c
  418. .)l
  419. .pp
  420. and the data structures themselves are defined in
  421. .pp
  422. .(l
  423. ~/src/lib/H/utils/dynamic_loader.h
  424. ~/src/lib/H/utils/fmgr.h
  425. ~/src/lib/H/utils/builtins.h
  426. ~/src/lib/H/catalog/pg_type.h
  427. .)l
  428. .p
  429. and
  430. .p
  431. .(l
  432. ~/src/utils/fmgr/fmgr.c
  433. .)l
  434. .pp
  435. .sh 3 "The Dynamic Loader"
  436. .pp
  437. The Dynamic Loader loads a user-defined function from a file and determines
  438. the names and addresses of each function in that file.  It then populates
  439. appropriate data structures with this information.  The source to the Dynamic
  440. Loader is in
  441. .pp
  442. .(l
  443. ~/src/utils/fmgr/dfmgr.c
  444. ~/src/port/*/dynloader.c
  445. .)l
  446. .sh 2 "General Algorithm"
  447. .pp
  448. The Postgres Function Manager uses the following general algorithm for
  449. determining the addresses of functions.  Once the address is found, the
  450. Function Manager Interface has functions which actually call the function.
  451. .pp
  452. .b General algorithm
  453. .pp
  454. Is function in builtin list?  If it is, return its address from this list
  455. .pp
  456. If the function is not in the list of builtins, it is a dynamically loaded
  457. function.  If so, look for the function name in the list of dynamically
  458. loaded functions.  If it is, return its address.
  459. .pp
  460. If the function has not yet been found, dynamically load it and determine
  461. its address.  Return this address.
  462. .pp
  463. .sh 1 "How does a user-defined function get executed?"
  464. .pp
  465. The program flow discussed in Section 3 - with the exception of the rule
  466. systems - is essentially similar to that of any data manager.  How, then, is
  467. Postgres so different?  The main differences between Postgres and other data
  468. managers is in its concept of what data is.  In Postgres, data is whatever
  469. the user says it is - the Postgres backend itself imposes no arbitrary
  470. definitions on data other than that it is a blob of memory of a known size.
  471. .pp
  472. The user defines what data is by defining functions and binding them to
  473. various operators.  These operators are then bound to user-defined types, and
  474. thus the system is complete.  In this section, how a user-defined function
  475. is executed will be discussed.
  476. .pp
  477. For the sake of this discussion (since operators will be discussed later), 
  478. assume that Postgres is operating on the following query
  479. .pp
  480. .(l
  481. * retrieve (emp.all) where overpaid(emp.salary)
  482. .)l
  483. and that overpaid(x) is a user-defined function taking an integer as an
  484. argument.  
  485. .pp
  486. Initially, the Parser will walk this query, and generate a parse tree.  While
  487. doing this, it will examine the following system classes:
  488. .pp
  489. .(l
  490. o  PG_PROC - information about Postgres functions is stored here.
  491. o  PG_TYPE - information about Postgres types is stored here.  
  492. .)l
  493. .pp
  494. PG_PROC contains information about the C file containing the function (if any),
  495. its return value, its number of arguments, its argument types, and other
  496. information.  The Parser will also check PG_TYPE to make sure that emp.salary
  497. is an appropriate argument for overpaid().  Once everything has been found to
  498. be proper, appropriate nodes containing information about the function will
  499. be inserted into the parsetree.
  500. .pp
  501. After the Planner has turned the parsetree into an execution plan, the Executor
  502. will walk the plan, executing overpaid() on each instance fetched from the "emp"
  503. class.  
  504. .pp
  505. The first time overpaid() is executed, the Executor will call the Postgres
  506. Function Manager to obtain the address of the function.  (See discussion in
  507. Section 5 for details on the Function Manager).  In subsequent calls, it will
  508. simply give Function Manager the address of the function so it can be called.
  509. .pp
  510. A user function like overpaid() is "registered" in Postgres using the Postquel
  511. .pp
  512. .(l
  513. DEFINE C FUNCTION
  514. .)l
  515. .pp
  516. query.
  517. .pp
  518. .sh 1 "How does a User Defined Operator get executed?"
  519. .pp
  520. When a user defines an operator, a user-defined function is associated with
  521. it.  Therefore, execution of an operator is little different than execution
  522. of a function, with only one major exception:  the Planner knows how to
  523. optimize operator queries but does not know how to deal with functions. 
  524. .pp
  525. The major system class dealing with operators is
  526. .pp
  527. .(l
  528. PG_OPERATOR
  529. .)l
  530. .pp
  531. Additionally, the same classes discussed in Section 6 are used in the execution
  532. of operators.  Binding of user functions to operators is handled with the
  533. Postquel
  534. .pp
  535. .(l
  536. DEFINE OPERATOR
  537. .)l
  538. .pp
  539. query.
  540. .pp
  541. .sh 1 "How is a User Defined Type handled?"
  542. .pp
  543. A User Defined Type minimally consists of two functions, the input function
  544. for the type, and the output function for the type.  Additionally, ordering
  545. (less than, greater than) and equality functions are necessary if the type is
  546. to be used in qualified queries, or if an index is to be defined on the type.  
  547. .pp
  548. In the system class
  549. .pp
  550. .(l
  551. PG_TYPE
  552. .)l
  553. .pp
  554. is information related to user-defined types, such as
  555. .pp
  556. .(l
  557. o  The names of the registered functions for input and output of the type.
  558. o  The size of the type
  559. .)l
  560. .pp
  561. The Postquel query
  562. .pp
  563. .(l
  564. DEFINE TYPE
  565. .)l
  566. populates the PG_TYPE class.
  567.