www.postgrespro.ru
ОБЗОР ИСХОДНОГО КОДА
Hacking PostgreSQL
17.03.2016
2
Содержание
1. Обзор source-tree
1. Утилиты и скрипты
2. Backend flowchart
2. Пример
3
postgres/
contrib – модули расширений
doc – документация (SGML)
src – ядро PostgreSQL
...
src/backend – сервер PostgreSQL ("Back-End")
src/bin – psql, pg_dump, initdb, и т.д. ("Front-End")
src/common – код, общий для front & back
src/include – .h файлы
src/interfaces – libpq, ecpg
src/pl – процедурные языки (plpgsql, plperl, plpython, tcl)
src/port – разные функции для портируемости
src/tools – инструменты для разработчиков (pgindent, и т.д.)
4
src/bin
Серверные утилиты
initdb – инициализация нового кластера баз данных PostgreSQL
pg_ctl – инициализация, запуск, останов и управление сервером
pg_controldata – вывод свойств, установленных командой initdb
pg_upgrade – обновление мажорной версии PostrgeSQL
pg_archivecleanup – очистка архивных WAL файлов
pg_resetxlog – очистка журнала упреждающей записи и другой
управляющей информацию кластера PostgreSQL
pg_xlogdump – вывод WAL файлов в удобном для чтения формате
pg_test_timing – измерение timing оверхеда
pg_rewind – синхронизация директорий PGDATA. Типичный сценарий –
восстановить упавший мастер как реплику нового мастера.
pg_test_fsync – определяет самый быстрый метод wal_sync_method
для конкретной системы
5
src/bin
Клиентские утилиты
psql – интерактивный терминал
pgevent
pg_dump – выгрузить базу данных PostgreSQL в формате скрипта в
файл или архив
pgbench – выполнение бенчмарков
pg_basebackup – создать резервную копию кластера PostgreSQL
pg_config – информация по конфигурационным параметрам
развёрнутого кластера
BINDIR = /home/anastasia/projects/postgresql_bin/bin
CONFIGURE = '­­enable­debug' 'CFLAGS=­O0' '­­enable­depend' '­­enable­
cassert' '­­prefix=/home/anastasia/projects/postgresql_bin/'
6
src/bin/scripts
Клиентские скрипты
clusterdb -- кластеризовать базу данных
createdb -- создать базу данных
createlang -- установить процедурный язык
createuser -- создать новую учётную запись
dropdb -- удалить базу данных
droplang -- удалить процедурный язык
dropuser -- удалить учётную запись пользователя
pg_isready -- проверить соединение с сервером
reindexdb -- переиндексировать базу данных
vacuumdb -- выполнить очистку и анализ базы данных
7
src/backend
8
src/backend
access - Методы доступа для разных структур данных (heap, btree indexes, gist, gin, brin…).
bootstrap - режим первоначальной загрузки
catalog - определения таблиц системного каталога
сommands - DDL и служебные команды (ALTER, CREATE TABLE, VACUUM, ...)
executor - выполнение запросов
foreign - Foreign Data Wrappers, user mappings, etc
lib - разные функции “общего назначения”
libpq - клиент-серверный протокол
main - основной процесс, передающий управление нужной подсистеме
nodes - обобщенная структура “Node” и функции из сравнения, копирования и т.д.
optimizer - оптимизатор запросов, реализует систему оценок стоимости и генерирует план
parser - лексер и парсер, разбор текста запросов
port - специфические функции для портирования
postmaster - основной процесс PostgreSQL
regex - Henry Spencer's regex library, also used by TCL, maintained more-or-less by PG now
replication – поддержка репликации, пересылка WAL-логов, чтение и т.д.
rewrite - перезапись запросов с использованием правил (RULE)
snowball - Snowball stemming, used with full-text search
storage - уровень хранилища, ввод/вывод, поддержка LO.
tcop - "Traffic Cop"- получение запросов и их обработка
tsearch - полнотекстовый поиск
utils - различные компоненты сервера, (кэш, управление памятью и т.д.)
9
10
Инициализация
bootstrap
Создание исходных баз через initdb.
main
Выполняет первоначальный запуск некоторых подсистем (например
error management и memory management), устанавливает информацию
о локали. Проверяет различные флаги и передает управление
процессу postmaster или postgres.
postmaster
Контролирует запуск и остановку сервера postgres. Создает
разделяемую память, а затем в цикле ждет запросов на подключение.
Сразу после получения такого запроса порождает backend процесс
postgres и передает управление ему.
libpq
Backend операции библиотеки libpq для взаимодействия с процессом
клиента.
11
initdb
src/bin/initdb/initdb.c – создание инстанса PostgreSQL.
Создание таблиц template0, template1 и postgres.
template0 – не изменяется после initdb
template1 – может содержать локальные данные
12
bootstrap
BKI – Backend Interface.
src/backend/bootstrap/bootstrap.c – функции для работы в режиме
инициализации кластера
pg_class, pg_attributes, pg_proc, pg_type – основные таблицы
каталога.
src/include/catalog/genbki.pl – скрипт на Perl, который генерирует
файл postgres.bki (и несколько других) из заголовочных файлов особого
формата src/include/catalog/pg_*.
src/backend/catalog/postgres.bki – создание таблиц каталога,
индексов и TOAST таблиц.
13
src/backend/postmaster
autovacuum.c
bgworker.c
bgwriter.c
checkpointer.c
fork_process.c
pgarch.c
pgstat.c
postmaster.c
startup.c – выполняет запуск сервера и восстановление (recovery).
syslogger.c
walwriter.c
14
Глобальные переменные
src/backend/utils/init/globals.c – объявления глобальных переменных
src/backend/utils/init/postinit.c – функции для инициализации
15
Клиент-серверный протокол
src/backend/libpq
●
TCP/IP протокол
●
Документация
●
Версия 2.0 начиная с 6.4, в 1999
●
Версия 3.0 начиная с 7.4, в 2003
●
Новые возможности 3.0:
– расширенный протокол запросов
– улучшения COPY
16
Формат сообщений
17
Формат передаваемых данных
src/backend/libpq/pqformat.c
●
Бинарный или текстовый форматы
●
Для разных типов данных разный формат.
●
Не документирован (кроме кода).
●
int8send, int8recv
●
json_send, jsonb_send
18
Простой запрос
19
Асинхронные операции
NoticeResponce – уведомления от сервера
ParameterStatus – уведомления об изменении параметров
NotificationResponse – сообщения, переданные через NOTIFY,
если клиент выполняет команду LISTEN
20
Отмена запроса
21
Прерывания
src/include/miscadmin.h
#define CHECK_FOR_INTERRUPTS() 
do { 
if (InterruptPending) 
ProcessInterrupts(); 
} while(0)
22
Подробнее
●
Презентация "Postgres on the wire"
●
Документация "Клиент-серверный протокол"
23
src/backend/parser
24
src/backend/parser/README
parser.c things start here
scan.l break query into tokens
scansup.c handle escapes in input strings
kwlookup.c turn keywords into specific tokens
keywords.c table of standard keywords (passed to kwlookup.c)
gram.y parse the tokens and produce a "raw" parse tree
analyze.c top level of parse analysis for optimizable queries
parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ...
parse_clause.c handle clauses like WHERE, ORDER BY, GROUP BY, ...
parse_coerce.c handle coercing expressions to different data types
parse_collate.c assign collation information in completed expressions
parse_cte.c handle Common Table Expressions (WITH clauses)
parse_expr.c handle expressions like col, col + 3, x = 3 or x = 4
parse_func.c handle functions, table.column and column identifiers
parse_node.c create nodes for various structures
parse_oper.c handle operators in expressions
parse_param.c handle Params (for the cases used in the core backend)
parse_relation.c support routines for tables and column handling
parse_target.c handle the result list of the query
parse_type.c support routines for data type handling
parse_utilcmd.c parse analysis for utility commands (done at execution time)
25
src/backend/parser/scan.l
digit [0-9]
integer {digit}+
decimal (({digit}*.{digit}+)|({digit}+.{digit}*))
{integer} {
SET_YYLLOC();
return process_integer_literal(yytext,
yylval);
}
{decimal} {
SET_YYLLOC();
yylval->str = pstrdup(yytext);
return FCONST;
}
26
src/backend/parser/gram.y
CreateStmt: CREATE OptTemp TABLE qualified_name
'(' OptTableElementList ')'
OptInherit OptWith OnCommitOption OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $6;
n->inhRelations = $8;
n->ofTypename = NULL;
n->constraints = NIL;
n->options = $9;
n->oncommit = $10;
n->tablespacename = $11;
n->if_not_exists = false;
$$ = (Node *)n;
}
27
DDL vs DML
28
DML
29
src/backend/nodes
30
Пример. CREATE TABLE
CREATE TABLE tbl (
a int, b int,
PRIMARY KEY (a) INCLUDING (b)
);
31
gram.y
CreateStmt: CREATE OptTemp TABLE qualified_name
'(' OptTableElementList ')'
OptInherit OptWith OnCommitOption OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $6;
n->inhRelations = $8;
n->ofTypename = NULL;
n->constraints = NIL;
n->options = $9;
n->oncommit = $10;
n->tablespacename = $11;
n->if_not_exists = false;
$$ = (Node *)n;
}
32
gram.y
| PRIMARY KEY '(' columnList ')' opt_c_including opt_definition
OptConsTableSpace ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
n->location = @1;
n->keys = $4;
n->including = $6;
n->options = $7;
n->indexname = NULL;
n->indexspace = $8;
processCASbits($9, @9, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (Node *)n;
}
opt_c_including: INCLUDING optcincluding { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
optcincluding : '(' columnList ')' { $$ = $2; }
;
33
src/include/nodes/parsenodes.h
typedef struct Query
{
NodeTag type;
CmdType commandType; /* select|insert|update|delete|utility */
QuerySource querySource; /* where did I come from? */
uint32 queryId; /* query identifier (can be set by plugins) */
bool canSetTag; /* do I set the command result tag? */
Node *utilityStmt; /* non-null if this is DECLARE CURSOR or a
* non-optimizable statement */
int resultRelation; /* rtable index of target relation for
* INSERT/UPDATE/DELETE; 0 for SELECT */
bool hasAggs; /* has aggregates in tlist or havingQual */
bool hasWindowFuncs; /* has window functions in tlist */
bool hasSubLinks; /* has subquery SubLink */
bool hasDistinctOn; /* distinctClause is from DISTINCT ON */
bool hasRecursive; /* WITH RECURSIVE was specified */
bool hasModifyingCTE; /* has INSERT/UPDATE/DELETE in WITH */
bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */
bool hasRowSecurity; /* row security applied? */
34
Query
List *cteList; /* WITH list (of CommonTableExpr's) */
List *rtable; /* list of range table entries */
FromExpr *jointree; /* table join tree (FROM and WHERE clauses) */
List *targetList; /* target list (of TargetEntry) */
OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */
List *returningList; /* return-values list (of TargetEntry) */
List *groupClause; /* a list of SortGroupClause's */
List *groupingSets; /* a list of GroupingSet's if present */
Node *havingQual; /* qualifications applied to groups */
List *windowClause; /* a list of WindowClause's */
List *distinctClause; /* a list of SortGroupClause's */
List *sortClause; /* a list of SortGroupClause's */
Node *limitOffset; /* # of result tuples to skip (int8 expr) */
Node *limitCount; /* # of result tuples to return (int8 expr) */
List *rowMarks; /* a list of RowMarkClause's */
Node *setOperations; /* set-operation tree if this is top level of
* a UNION/INTERSECT/EXCEPT query */
List *constraintDeps; /* a list of pg_constraint OIDs that the query
* depends on to be semantically valid */
...
} Query;
35
CreateStmt
typedef struct CreateStmt
{
NodeTag type;
RangeVar *relation; /* relation to create */
List *tableElts; /* column definitions (list of ColumnDef) */
List *inhRelations; /* relations to inherit from (list of
* inhRelation) */
TypeName *ofTypename; /* OF typename */
List *constraints; /* constraints (list of Constraint nodes) */
List *options; /* options from WITH clause */
OnCommitAction oncommit; /* what do we do at COMMIT? */
char *tablespacename; /* table space to use, or NULL */
bool if_not_exists; /* just do nothing if it already exists? */
} CreateStmt;
36
Constraint
typedef struct Constraint
{
NodeTag type;
ConstrType contype; /* see above */
/* Fields used for most/all constraint types: */
char *conname; /* Constraint name, or NULL if unnamed */
bool deferrable; /* DEFERRABLE? */
bool initdeferred; /* INITIALLY DEFERRED? */
int location; /* token location, or -1 if unknown */
/* Fields used for unique constraints (UNIQUE and PRIMARY KEY): */
List *keys; /* String nodes naming referenced key column(s) */
List *including; /* String nodes naming referenced nonkey
* column(s) */
...
}
37
tcop/utility.c
ProcessUtilitySlow {
switch (nodeTag(parsetree)) {
case T_CreateStmt:
/* Run parse analysis ... */
stmts = transformCreateStmt((CreateStmt *) parsetree,
queryString);
foreach(l, stmts) {
if (IsA(stmt, CreateStmt)) {
/* Create the table itself */
address = DefineRelation((CreateStmt *) stmt,
RELKIND_RELATION,
InvalidOid, NULL);
}
else {
/*
* Recurse for anything else.
*/
ProcessUtility(...)
}
}
38
parse_utilcmd.c
transformCreateStmt {
transformTableConstraint {
switch (constraint→contype)
{
case CONSTR_PRIMARY:
cxt->ixconstraints = lappend(cxt->ixconstraints,
constraint);
Break;
}
}
transformIndexConstraints {
foreach(lc, cxt->ixconstraints)
{
Constraint *constraint = (Constraint *) lfirst(lc);
index = transformIndexConstraint(constraint, cxt);
indexlist = lappend(indexlist, index);
}
}
}
39
parse_utilcmd.c
transformIndexConstraint {
foreach(lc, constraint->including)
{
...
/* add it to the index definition*/
iparam = makeNode(IndexElem);
iparam->name = pstrdup(key);
iparam->expr = NULL;
iparam->indexcolname = NULL;
iparam->collation = NIL;
iparam->opclass = NIL;
index->indexIncludingParams = lappend(index-
>indexIncludingParams, iparam);
}
}
40
indexcmds.c
ObjectAddress
DefineIndex(Oid relationId, IndexStmt *stmt, …) {
indexRelationId = index_create(rel, indexRelationName,
indexRelationId, stmt→oldNode,
indexInfo, indexColNames,
accessMethodId, tablespaceId,
collationObjectId, classObjectId,
coloptions, reloptions,
stmt->primary,stmt->isconstraint,
stmt->deferrable, stmt->initdeferred,
allowSystemTableMods,
skip_build || stmt->concurrent,
stmt->concurrent, !check_rights,
stmt→if_not_exists);
}
41
Продолжение следует...
В следующий раз:
– Физическое представление данных
– Методы доступа
– Внутренняя структура tuple
www.postgrespro.ru
СПАСИБО ЗА ВНИМАНИЕ!
ВОПРОСЫ?
Hacking PostgreSQL
17.03.2016
hacking@postgrespro.ru

Hacking PostgreSQL. Обзор исходного кода

  • 1.
  • 2.
    2 Содержание 1. Обзор source-tree 1.Утилиты и скрипты 2. Backend flowchart 2. Пример
  • 3.
    3 postgres/ contrib – модулирасширений doc – документация (SGML) src – ядро PostgreSQL ... src/backend – сервер PostgreSQL ("Back-End") src/bin – psql, pg_dump, initdb, и т.д. ("Front-End") src/common – код, общий для front & back src/include – .h файлы src/interfaces – libpq, ecpg src/pl – процедурные языки (plpgsql, plperl, plpython, tcl) src/port – разные функции для портируемости src/tools – инструменты для разработчиков (pgindent, и т.д.)
  • 4.
    4 src/bin Серверные утилиты initdb –инициализация нового кластера баз данных PostgreSQL pg_ctl – инициализация, запуск, останов и управление сервером pg_controldata – вывод свойств, установленных командой initdb pg_upgrade – обновление мажорной версии PostrgeSQL pg_archivecleanup – очистка архивных WAL файлов pg_resetxlog – очистка журнала упреждающей записи и другой управляющей информацию кластера PostgreSQL pg_xlogdump – вывод WAL файлов в удобном для чтения формате pg_test_timing – измерение timing оверхеда pg_rewind – синхронизация директорий PGDATA. Типичный сценарий – восстановить упавший мастер как реплику нового мастера. pg_test_fsync – определяет самый быстрый метод wal_sync_method для конкретной системы
  • 5.
    5 src/bin Клиентские утилиты psql –интерактивный терминал pgevent pg_dump – выгрузить базу данных PostgreSQL в формате скрипта в файл или архив pgbench – выполнение бенчмарков pg_basebackup – создать резервную копию кластера PostgreSQL pg_config – информация по конфигурационным параметрам развёрнутого кластера BINDIR = /home/anastasia/projects/postgresql_bin/bin CONFIGURE = '­­enable­debug' 'CFLAGS=­O0' '­­enable­depend' '­­enable­ cassert' '­­prefix=/home/anastasia/projects/postgresql_bin/'
  • 6.
    6 src/bin/scripts Клиентские скрипты clusterdb --кластеризовать базу данных createdb -- создать базу данных createlang -- установить процедурный язык createuser -- создать новую учётную запись dropdb -- удалить базу данных droplang -- удалить процедурный язык dropuser -- удалить учётную запись пользователя pg_isready -- проверить соединение с сервером reindexdb -- переиндексировать базу данных vacuumdb -- выполнить очистку и анализ базы данных
  • 7.
  • 8.
    8 src/backend access - Методыдоступа для разных структур данных (heap, btree indexes, gist, gin, brin…). bootstrap - режим первоначальной загрузки catalog - определения таблиц системного каталога сommands - DDL и служебные команды (ALTER, CREATE TABLE, VACUUM, ...) executor - выполнение запросов foreign - Foreign Data Wrappers, user mappings, etc lib - разные функции “общего назначения” libpq - клиент-серверный протокол main - основной процесс, передающий управление нужной подсистеме nodes - обобщенная структура “Node” и функции из сравнения, копирования и т.д. optimizer - оптимизатор запросов, реализует систему оценок стоимости и генерирует план parser - лексер и парсер, разбор текста запросов port - специфические функции для портирования postmaster - основной процесс PostgreSQL regex - Henry Spencer's regex library, also used by TCL, maintained more-or-less by PG now replication – поддержка репликации, пересылка WAL-логов, чтение и т.д. rewrite - перезапись запросов с использованием правил (RULE) snowball - Snowball stemming, used with full-text search storage - уровень хранилища, ввод/вывод, поддержка LO. tcop - "Traffic Cop"- получение запросов и их обработка tsearch - полнотекстовый поиск utils - различные компоненты сервера, (кэш, управление памятью и т.д.)
  • 9.
  • 10.
    10 Инициализация bootstrap Создание исходных базчерез initdb. main Выполняет первоначальный запуск некоторых подсистем (например error management и memory management), устанавливает информацию о локали. Проверяет различные флаги и передает управление процессу postmaster или postgres. postmaster Контролирует запуск и остановку сервера postgres. Создает разделяемую память, а затем в цикле ждет запросов на подключение. Сразу после получения такого запроса порождает backend процесс postgres и передает управление ему. libpq Backend операции библиотеки libpq для взаимодействия с процессом клиента.
  • 11.
    11 initdb src/bin/initdb/initdb.c – созданиеинстанса PostgreSQL. Создание таблиц template0, template1 и postgres. template0 – не изменяется после initdb template1 – может содержать локальные данные
  • 12.
    12 bootstrap BKI – BackendInterface. src/backend/bootstrap/bootstrap.c – функции для работы в режиме инициализации кластера pg_class, pg_attributes, pg_proc, pg_type – основные таблицы каталога. src/include/catalog/genbki.pl – скрипт на Perl, который генерирует файл postgres.bki (и несколько других) из заголовочных файлов особого формата src/include/catalog/pg_*. src/backend/catalog/postgres.bki – создание таблиц каталога, индексов и TOAST таблиц.
  • 13.
  • 14.
    14 Глобальные переменные src/backend/utils/init/globals.c –объявления глобальных переменных src/backend/utils/init/postinit.c – функции для инициализации
  • 15.
    15 Клиент-серверный протокол src/backend/libpq ● TCP/IP протокол ● Документация ● Версия2.0 начиная с 6.4, в 1999 ● Версия 3.0 начиная с 7.4, в 2003 ● Новые возможности 3.0: – расширенный протокол запросов – улучшения COPY
  • 16.
  • 17.
    17 Формат передаваемых данных src/backend/libpq/pqformat.c ● Бинарныйили текстовый форматы ● Для разных типов данных разный формат. ● Не документирован (кроме кода). ● int8send, int8recv ● json_send, jsonb_send
  • 18.
  • 19.
    19 Асинхронные операции NoticeResponce –уведомления от сервера ParameterStatus – уведомления об изменении параметров NotificationResponse – сообщения, переданные через NOTIFY, если клиент выполняет команду LISTEN
  • 20.
  • 21.
    21 Прерывания src/include/miscadmin.h #define CHECK_FOR_INTERRUPTS() do{ if (InterruptPending) ProcessInterrupts(); } while(0)
  • 22.
    22 Подробнее ● Презентация "Postgres onthe wire" ● Документация "Клиент-серверный протокол"
  • 23.
  • 24.
    24 src/backend/parser/README parser.c things starthere scan.l break query into tokens scansup.c handle escapes in input strings kwlookup.c turn keywords into specific tokens keywords.c table of standard keywords (passed to kwlookup.c) gram.y parse the tokens and produce a "raw" parse tree analyze.c top level of parse analysis for optimizable queries parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ... parse_clause.c handle clauses like WHERE, ORDER BY, GROUP BY, ... parse_coerce.c handle coercing expressions to different data types parse_collate.c assign collation information in completed expressions parse_cte.c handle Common Table Expressions (WITH clauses) parse_expr.c handle expressions like col, col + 3, x = 3 or x = 4 parse_func.c handle functions, table.column and column identifiers parse_node.c create nodes for various structures parse_oper.c handle operators in expressions parse_param.c handle Params (for the cases used in the core backend) parse_relation.c support routines for tables and column handling parse_target.c handle the result list of the query parse_type.c support routines for data type handling parse_utilcmd.c parse analysis for utility commands (done at execution time)
  • 25.
    25 src/backend/parser/scan.l digit [0-9] integer {digit}+ decimal(({digit}*.{digit}+)|({digit}+.{digit}*)) {integer} { SET_YYLLOC(); return process_integer_literal(yytext, yylval); } {decimal} { SET_YYLLOC(); yylval->str = pstrdup(yytext); return FCONST; }
  • 26.
    26 src/backend/parser/gram.y CreateStmt: CREATE OptTempTABLE qualified_name '(' OptTableElementList ')' OptInherit OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; n->relation = $4; n->tableElts = $6; n->inhRelations = $8; n->ofTypename = NULL; n->constraints = NIL; n->options = $9; n->oncommit = $10; n->tablespacename = $11; n->if_not_exists = false; $$ = (Node *)n; }
  • 27.
  • 28.
  • 29.
  • 30.
    30 Пример. CREATE TABLE CREATETABLE tbl ( a int, b int, PRIMARY KEY (a) INCLUDING (b) );
  • 31.
    31 gram.y CreateStmt: CREATE OptTempTABLE qualified_name '(' OptTableElementList ')' OptInherit OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; n->relation = $4; n->tableElts = $6; n->inhRelations = $8; n->ofTypename = NULL; n->constraints = NIL; n->options = $9; n->oncommit = $10; n->tablespacename = $11; n->if_not_exists = false; $$ = (Node *)n; }
  • 32.
    32 gram.y | PRIMARY KEY'(' columnList ')' opt_c_including opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_PRIMARY; n->location = @1; n->keys = $4; n->including = $6; n->options = $7; n->indexname = NULL; n->indexspace = $8; processCASbits($9, @9, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner); $$ = (Node *)n; } opt_c_including: INCLUDING optcincluding { $$ = $2; } | /* EMPTY */ { $$ = NIL; } ; optcincluding : '(' columnList ')' { $$ = $2; } ;
  • 33.
    33 src/include/nodes/parsenodes.h typedef struct Query { NodeTagtype; CmdType commandType; /* select|insert|update|delete|utility */ QuerySource querySource; /* where did I come from? */ uint32 queryId; /* query identifier (can be set by plugins) */ bool canSetTag; /* do I set the command result tag? */ Node *utilityStmt; /* non-null if this is DECLARE CURSOR or a * non-optimizable statement */ int resultRelation; /* rtable index of target relation for * INSERT/UPDATE/DELETE; 0 for SELECT */ bool hasAggs; /* has aggregates in tlist or havingQual */ bool hasWindowFuncs; /* has window functions in tlist */ bool hasSubLinks; /* has subquery SubLink */ bool hasDistinctOn; /* distinctClause is from DISTINCT ON */ bool hasRecursive; /* WITH RECURSIVE was specified */ bool hasModifyingCTE; /* has INSERT/UPDATE/DELETE in WITH */ bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */ bool hasRowSecurity; /* row security applied? */
  • 34.
    34 Query List *cteList; /*WITH list (of CommonTableExpr's) */ List *rtable; /* list of range table entries */ FromExpr *jointree; /* table join tree (FROM and WHERE clauses) */ List *targetList; /* target list (of TargetEntry) */ OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */ List *returningList; /* return-values list (of TargetEntry) */ List *groupClause; /* a list of SortGroupClause's */ List *groupingSets; /* a list of GroupingSet's if present */ Node *havingQual; /* qualifications applied to groups */ List *windowClause; /* a list of WindowClause's */ List *distinctClause; /* a list of SortGroupClause's */ List *sortClause; /* a list of SortGroupClause's */ Node *limitOffset; /* # of result tuples to skip (int8 expr) */ Node *limitCount; /* # of result tuples to return (int8 expr) */ List *rowMarks; /* a list of RowMarkClause's */ Node *setOperations; /* set-operation tree if this is top level of * a UNION/INTERSECT/EXCEPT query */ List *constraintDeps; /* a list of pg_constraint OIDs that the query * depends on to be semantically valid */ ... } Query;
  • 35.
    35 CreateStmt typedef struct CreateStmt { NodeTagtype; RangeVar *relation; /* relation to create */ List *tableElts; /* column definitions (list of ColumnDef) */ List *inhRelations; /* relations to inherit from (list of * inhRelation) */ TypeName *ofTypename; /* OF typename */ List *constraints; /* constraints (list of Constraint nodes) */ List *options; /* options from WITH clause */ OnCommitAction oncommit; /* what do we do at COMMIT? */ char *tablespacename; /* table space to use, or NULL */ bool if_not_exists; /* just do nothing if it already exists? */ } CreateStmt;
  • 36.
    36 Constraint typedef struct Constraint { NodeTagtype; ConstrType contype; /* see above */ /* Fields used for most/all constraint types: */ char *conname; /* Constraint name, or NULL if unnamed */ bool deferrable; /* DEFERRABLE? */ bool initdeferred; /* INITIALLY DEFERRED? */ int location; /* token location, or -1 if unknown */ /* Fields used for unique constraints (UNIQUE and PRIMARY KEY): */ List *keys; /* String nodes naming referenced key column(s) */ List *including; /* String nodes naming referenced nonkey * column(s) */ ... }
  • 37.
    37 tcop/utility.c ProcessUtilitySlow { switch (nodeTag(parsetree)){ case T_CreateStmt: /* Run parse analysis ... */ stmts = transformCreateStmt((CreateStmt *) parsetree, queryString); foreach(l, stmts) { if (IsA(stmt, CreateStmt)) { /* Create the table itself */ address = DefineRelation((CreateStmt *) stmt, RELKIND_RELATION, InvalidOid, NULL); } else { /* * Recurse for anything else. */ ProcessUtility(...) } }
  • 38.
    38 parse_utilcmd.c transformCreateStmt { transformTableConstraint { switch(constraint→contype) { case CONSTR_PRIMARY: cxt->ixconstraints = lappend(cxt->ixconstraints, constraint); Break; } } transformIndexConstraints { foreach(lc, cxt->ixconstraints) { Constraint *constraint = (Constraint *) lfirst(lc); index = transformIndexConstraint(constraint, cxt); indexlist = lappend(indexlist, index); } } }
  • 39.
    39 parse_utilcmd.c transformIndexConstraint { foreach(lc, constraint->including) { ... /*add it to the index definition*/ iparam = makeNode(IndexElem); iparam->name = pstrdup(key); iparam->expr = NULL; iparam->indexcolname = NULL; iparam->collation = NIL; iparam->opclass = NIL; index->indexIncludingParams = lappend(index- >indexIncludingParams, iparam); } }
  • 40.
    40 indexcmds.c ObjectAddress DefineIndex(Oid relationId, IndexStmt*stmt, …) { indexRelationId = index_create(rel, indexRelationName, indexRelationId, stmt→oldNode, indexInfo, indexColNames, accessMethodId, tablespaceId, collationObjectId, classObjectId, coloptions, reloptions, stmt->primary,stmt->isconstraint, stmt->deferrable, stmt->initdeferred, allowSystemTableMods, skip_build || stmt->concurrent, stmt->concurrent, !check_rights, stmt→if_not_exists); }
  • 41.
    41 Продолжение следует... В следующийраз: – Физическое представление данных – Методы доступа – Внутренняя структура tuple
  • 42.