From: Nikolay Shaplov Date: Fri, 7 Nov 2025 06:42:12 +0000 (+0300) Subject: Переместил все лекции про разработку PostgreSQL в отдельную директорию X-Git-Url: http://gitweb.nataraj.world/?a=commitdiff_plain;h=e8e8d64ecfacd1da4ddb7f5f2623cf4a6173350c;p=articles.git Переместил все лекции про разработку PostgreSQL в отдельную директорию --- diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.odp b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.odp new file mode 100644 index 0000000..c7faadb Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.odp differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.pdf b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.pdf new file mode 100644 index 0000000..e5a329d Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.pdf differ diff --git "a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" new file mode 100644 index 0000000..6c04d17 Binary files /dev/null and "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" differ diff --git "a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" new file mode 100644 index 0000000..6ee00ce Binary files /dev/null and "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" differ diff --git "a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" new file mode 100644 index 0000000..58133f2 Binary files /dev/null and "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" differ diff --git "a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" new file mode 100644 index 0000000..07f2634 Binary files /dev/null and "b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-10 - Creating own extension, Nepal/Creating_extension_2025.odp b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-10 - Creating own extension, Nepal/Creating_extension_2025.odp new file mode 100644 index 0000000..42b45d0 Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/2025-10 - Creating own extension, Nepal/Creating_extension_2025.odp differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/README.md b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/README.md new file mode 100644 index 0000000..ca496a5 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/README.md @@ -0,0 +1,10 @@ +### Аннотация + +#### Создание расширения PostgreSQL +#### Первый шаг на пути к разработке ядра postgres. + +Популярность PostgreSQL обеспечивается не только ее производительностью и доступностью, но во многом своим открытым процессом разработки: исходный код СУБД доступен для изучения и модификации, и любой желающий может принять участие в разработке ядра проекта, предлагая свое улучшения и изменения. +Программист для того чтобы стать ядра разработчиком ядра PostgreSQL должен пройти длинный путь, но практически каждый начинает свое движение с разработки расширения PostgreSQL. +PostgreSQL предоставляет широкие возможности по расширению функциональности и модификации поведения ядра СУБД через механизм расширений. + +В этой лекции мы рассмотрим основы создания расширений: что это такое, из каких элементов оно состоит, и создадим первое учебное расширение. diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/log.log b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/log.log new file mode 100644 index 0000000..5832a3c --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/log.log @@ -0,0 +1,361 @@ +Extension is a set of PostgreSQL objects that can be `CREATE`ed. +Like `CREATE FUNCTION`, `CREATE TYPE` or `CREATE OPERATOR`. +This set is created, updated and deleted as a bundle. +When you do `CREATE EXTENSION` you it will create all object included into extension. +When you do `DROP EXTENSION` all that objects will be automatically removed. + +So extension is just a set of SQL commands to create or update extension schema. +(You even do not need to delete it, `DROP EXTENSION` will delete them automatically) + +Functions may be written in `PL/pgSQL` or other `PL/*` or you can load binary function from shared `.so` library. +. +You can register a function as a hook handler to change behavior if PostgreSQL. + + + +See https://github.com/IshaanAdarsh/Postgres-extension-tutorial/blob/main/SGML/Main.md for more info + +``` + +$ whoami +nataraj + +$ sudo -u postgres createuser -s nataraj +``` + +Make sure that `-dev` files for postgres are installed. In Debian-based distributives it wil +be like this + +``` +sudo apt-get install postgresql-server-dev-all + +``` + + +``` +$ mkdir my_first_extension + +$ cd my_first_extension +``` + +``` +touch my_first_extension.control +``` + +``` +# my_first_extension.control +# Comment line to provide additional information about the extension +comment = 'My Very First Extension' + +# Specifies the default version of the extension +default_version = '0.0.1' +``` + +https://www.postgresql.org/docs/17/extend-extensions.html#EXTEND-EXTENSIONS-FILES + + +--- + +``` +touch my_first_extension--0.0.1.sql +``` + +``` +CREATE TABLE my_first_extension_table ( + id SERIAL PRIMARY KEY, + my_string VARCHAR NOT NULL +); + +INSERT INTO my_first_extension_table (my_string) VALUES('Hello, World'); +``` + +--- + +``` +touch Makefile +``` + +``` +EXTENSION = my_first_extension # Name of the extension +DATA = my_first_extension--0.0.1.sql # SQL file containing extension objects and functions + +PG_CONFIG ?= pg_config # Path to the pg_config executable +PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config +include $(PGXS) # Include the PostgreSQL Extension Makefile +``` + +--- + +``` +make +sudo make install +``` + +``` +sudo -u postgres psql + +# CREATE EXTENSION my_first_extension; +CREATE EXTENSION + +# SELECT * FROM my_first_extension_table; + id | my_string +----+-------------- + 1 | Hello, World +(1 row) + +# DROP EXTENSION my_first_extension; +DROP EXTENSION + +# SELECT * FROM my_first_extension_table; +ERROR: relation "my_first_extension_table" does not exist +СТРОКА 1: SELECT * FROM my_first_extension_table; + ^ +``` + +------------ + +# Add tests + +``` +mkdir sql +``` + +edit `sql/my_first_extension-main-test.sql` + +``` +CREATE EXTENSION my_first_extension; + +SELECT * FROM my_first_extension_table; + +DROP EXTENSION + +-- There should be no my_first_extension_table anymore +SELECT * FROM my_first_extension_table; +``` + +---- + +change Makefile + +``` +EXTENSION = my_first_extension # Name of the extension +DATA = my_first_extension--0.0.1.sql # SQL file containing extension objects and functions +REGRESS = my_first_extension-main-test + + +PG_CONFIG ?= pg_config # Path to the pg_config executable +PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config +include $(PGXS) # Include the PostgreSQL Extension Makefile +``` + +run `make installcheck` + + +and get an error: `my_first_extension/expected/my_first_extension-main-test.out: No such file or directory` + +and a `results` dir. + +---- + +Check that `results/my_first_extension-main-test.out` is what you expect + +``` +$ cat results/my_first_extension-main-test.out +CREATE EXTENSION my_first_extension; +SELECT * FROM my_first_extension_table; + id | my_string +----+-------------- + 1 | Hello, World +(1 row) + +DROP EXTENSION +-- There should be no my_first_extension_table anymore +SELECT * FROM my_first_extension_table; +ERROR: syntax error at or near "SELECT" +LINE 3: SELECT * FROM my_first_extension_table; + ^ +``` + +---- + +If everything as you expected copy `my_first_extension-main-test.out` from `results` dir to `expected` + +``` +mkdir expected +cp results/my_first_extension-main-test.out expected +``` + +---- + +Now tests should pass + +``` +n$ make installcheck +echo "+++ regress install-check in +++" && /usr/lib/postgresql/15/lib/pgxs/src/makefiles/../../src/test/regress/pg_regress --inputdir=./ --bindir='/usr/lib/postgresql/15/bin' --dbname=contrib_regression my_first_extension-main-test ++++ regress install-check in +++ +(using postmaster on Unix socket, default port) +============== dropping database "contrib_regression" ============== +SET +DROP DATABASE +============== creating database "contrib_regression" ============== +CREATE DATABASE +ALTER DATABASE +ALTER DATABASE +ALTER DATABASE +ALTER DATABASE +ALTER DATABASE +ALTER DATABASE +============== running regression test queries ============== +test my_first_extension-main-test ... ok 54 ms + +===================== + All 1 tests passed. +===================== +``` + +----- + +Now let's create create a new version of extension, with a plpsql function in it + +* Change version from `0.0.1` to `0.0.2` in `my_first_extension.control`: + +``` +default_version = '0.0.2' +``` + +* rename schema creation file from `my_first_extension--0.0.1.sql` to `my_first_extension--0.0.2.sql` +* create an schema update file `my_first_extension--0.0.1--0.0.2.sql` + +Add to both of them function creation code + +``` +CREATE FUNCTION my_one() +returns int +language plpgsql +as +$$ +begin + return 1; +end; +$$; + +``` + +* Update `Makefile` adding new sql file names to `DATA` variable + +``` +DATA = my_first_extension--0.0.2.sql my_first_extension--0.0.1--0.0.2.sql +``` + +* install extension + +``` +sudo make install + +``` + +* check everything works + +``` +$ sudo -u postgres psql + +=# CREATE EXTENSION my_first_extension; +CREATE EXTENSION + +s=# SELECT my_one(); + my_one +-------- + 1 +(1 row) +``` + +---- + +Write test for `my_one` function yourself + +---- + +https://www.highgo.ca/2020/01/10/how-to-create-test-and-debug-an-extension-written-in-c-for-postgresql/ + + +Creating C-function + +// Do not forget to install `postgresql-server-dev-all` + +create `my_first_extension.c` file + +``` +#include "postgres.h" +#include "fmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(my_get_two); + +Datum +my_get_two(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT32(2); +} +``` + +add following lines to `Makefile` + +``` +MODULE_big = my_first_extension +OBJS = my_first_extension.o + +``` +and to the `my_first_extension.control` + + +``` +module_pathname = '$libdir/my_first_extension' + +``` + + +Check everything works well by running + +``` +make +``` + +add to schema +``` +CREATE FUNCTION my_two() +RETURNS INT +AS 'MODULE_PATHNAME', 'my_get_two' +LANGUAGE C; +``` + + +bump version in *.sql files, Makefile and control file + + +``` +make +sudo make install +``` + +Check everything works: + +``` +$ sudo -u postgres psql + +=# DROP EXTENSION my_first_extension; +DROP EXTENSION + +=# CREATE EXTENSION my_first_extension; +CREATE EXTENSION +postgres=# SELECT my_two(); + my_two +-------- + 2 +(1 row) + +``` + +Do not forget to write tests! + + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/Makefile b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/Makefile new file mode 100644 index 0000000..4b14455 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/Makefile @@ -0,0 +1,13 @@ +MODULE_big = my_first_extension +EXTENSION = my_first_extension # Name of the extension +DATA = my_first_extension--0.0.3.sql my_first_extension--0.0.1--0.0.2.sql my_first_extension--0.0.2--0.0.3.sql +REGRESS = my_first_extension-main-test + +OBJS = my_first_extension.o + + +PG_CONFIG ?= pg_config # Path to the pg_config executable +PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config +include $(PGXS) # Include the PostgreSQL Extension Makefile + + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/expected/my_first_extension-main-test.out b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/expected/my_first_extension-main-test.out new file mode 100644 index 0000000..a0b8cc9 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/expected/my_first_extension-main-test.out @@ -0,0 +1,13 @@ +CREATE EXTENSION my_first_extension; +SELECT * FROM my_first_extension_table; + id | my_string +----+-------------- + 1 | Hello, World +(1 row) + +DROP EXTENSION my_first_extension; +-- There should be no my_first_extension_table anymore +SELECT * FROM my_first_extension_table; +ERROR: relation "my_first_extension_table" does not exist +LINE 1: SELECT * FROM my_first_extension_table; + ^ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.1--0.0.2.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.1--0.0.2.sql new file mode 100644 index 0000000..9c107ac --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.1--0.0.2.sql @@ -0,0 +1,10 @@ +CREATE FUNCTION my_one() +returns int +language plpgsql +as +$$ +begin + return 1; +end; +$$; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.2--0.0.3.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.2--0.0.3.sql new file mode 100644 index 0000000..7b9adcd --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.2--0.0.3.sql @@ -0,0 +1,5 @@ +CREATE FUNCTION my_two() +RETURNS INT +AS 'MODULE_PATHNAME', 'my_get_two' +LANGUAGE C; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.3.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.3.sql new file mode 100644 index 0000000..b25f223 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension--0.0.3.sql @@ -0,0 +1,24 @@ +CREATE TABLE my_first_extension_table ( + id SERIAL PRIMARY KEY, + my_string VARCHAR NOT NULL +); + +INSERT INTO my_first_extension_table (my_string) VALUES('Hello, World'); + + +CREATE FUNCTION my_one() +returns int +language plpgsql +as +$$ +begin + return 1; +end; +$$; + + +CREATE FUNCTION my_two() +RETURNS INT +AS 'MODULE_PATHNAME', 'my_get_two' +LANGUAGE C; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension.c b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension.c new file mode 100644 index 0000000..a126494 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension.c @@ -0,0 +1,12 @@ +#include "postgres.h" +#include "fmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(my_get_two); + +Datum +my_get_two(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT32(2); +} diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension.control b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension.control new file mode 100644 index 0000000..68688a0 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/my_first_extension.control @@ -0,0 +1,8 @@ +# my_first_extension.control +# Comment line to provide additional information about the extension +comment = 'My Very First Extension' + +# Specifies the default version of the extension +default_version = '0.0.3' +module_pathname = '$libdir/my_first_extension' + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/sql/my_first_extension-main-test.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/sql/my_first_extension-main-test.sql new file mode 100644 index 0000000..8992652 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/1. Creating own extension/code/my_first_extension/sql/my_first_extension-main-test.sql @@ -0,0 +1,9 @@ +CREATE EXTENSION my_first_extension; + +SELECT * FROM my_first_extension_table; + +DROP EXTENSION my_first_extension; + +-- There should be no my_first_extension_table anymore +SELECT * FROM my_first_extension_table; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/2025 - Basic Structures - Register Data Types - Eng/basic_structures-2025.odp b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/2025 - Basic Structures - Register Data Types - Eng/basic_structures-2025.odp new file mode 100644 index 0000000..e42e7be Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/2025 - Basic Structures - Register Data Types - Eng/basic_structures-2025.odp differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/basic_structures-2025.odp b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/basic_structures-2025.odp new file mode 100644 index 0000000..256f122 Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/basic_structures-2025.odp differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/basic_structures-2025.pdf b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/basic_structures-2025.pdf new file mode 100644 index 0000000..0fcab67 Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/basic_structures-2025.pdf differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/Makefile b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/Makefile new file mode 100644 index 0000000..6ccf984 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/Makefile @@ -0,0 +1,13 @@ +MODULE_big = data_types_examples +EXTENSION = data_types_examples # Name of the extension +DATA = data_types_examples--0.0.1.sql +# REGRESS = my_first_extension-main-test + +OBJS = data_types_examples.o warn_me.o my_factorial.o hello_world.o + + +PG_CONFIG ?= pg_config # Path to the pg_config executable +PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config +include $(PGXS) # Include the PostgreSQL Extension Makefile + + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql new file mode 100644 index 0000000..e6e370a --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql @@ -0,0 +1,17 @@ + + +CREATE FUNCTION warn_me(int) RETURNS int +AS 'MODULE_PATHNAME', 'warn_me' +LANGUAGE C; + + +CREATE FUNCTION my_factorial(int) RETURNS int +AS 'MODULE_PATHNAME', 'my_factorial' +LANGUAGE C; + + +CREATE FUNCTION hello_world() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world' +LANGUAGE C; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c new file mode 100644 index 0000000..e53bb30 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c @@ -0,0 +1,13 @@ +#include "postgres.h" +#include "fmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(my_inc); + +Datum +my_inc(PG_FUNCTION_ARGS) +{ + + PG_RETURN_INT32(2); +} diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control new file mode 100644 index 0000000..99d98e9 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control @@ -0,0 +1,8 @@ +# my_first_extension.control +# Comment line to provide additional information about the extension +comment = 'Data Types Exampls' + +# Specifies the default version of the extension +default_version = '0.0.1' +module_pathname = '$libdir/data_types_examples' + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/hello_world.c b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/hello_world.c new file mode 100644 index 0000000..34e079f --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/hello_world.c @@ -0,0 +1,17 @@ +#include "postgres.h" +#include "fmgr.h" +#include "utils/builtins.h" + +PG_FUNCTION_INFO_V1(hello_world); + +Datum +hello_world(PG_FUNCTION_ARGS) +{ + char message[] = "Hello, World!"; + Datum datum; + + datum = CStringGetTextDatum(message); + + PG_RETURN_TEXT_P(datum); +} + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c new file mode 100644 index 0000000..2e60743 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c @@ -0,0 +1,24 @@ +#include "postgres.h" +#include "fmgr.h" + +PG_FUNCTION_INFO_V1(my_factorial); + +Datum +my_factorial(PG_FUNCTION_ARGS) +{ + int32 res, n = PG_GETARG_INT32(0); + Datum d; + + if (n < 0) + elog(ERROR, "Так нельзя!"); + + if (n == 0) + PG_RETURN_INT32(1); + + d = DirectFunctionCall1(my_factorial, Int32GetDatum(n - 1)); + + res = DatumGetInt32(d) * n; + + PG_RETURN_INT32(res); +} + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c new file mode 100644 index 0000000..4da0231 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c @@ -0,0 +1,13 @@ +#include "postgres.h" +#include "fmgr.h" + +PG_FUNCTION_INFO_V1(warn_me); + +Datum +warn_me(PG_FUNCTION_ARGS) +{ + int32 n = PG_GETARG_INT32(0); + elog(WARNING, "Предупреждаю: %i", n); + PG_RETURN_INT32(n); +} + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/log.md b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/log.md new file mode 100644 index 0000000..c07b876 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/2. Basic Structures: Register Data Types/src/log.md @@ -0,0 +1,247 @@ + +* Свободное ПО замечательно тем, что всегда можно самому посмтреть как и что устроено + +*Сеанс белой магии с разоблачениями* + +Не только знания о структуре, но и навыки работы с кодом + + +## Стандартные арифметические типы + +Исторические причины: + +* Postgres95 моложе С99 +* Сколько байт займет `signed i;` ? + +Поэтому: + +``` +/* Historical names for types in . */ +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; +``` +`src/include/c.h` + +## Волшебные макросы pg-функций + +"С-Программист, помни! Макрос -- твой лучший друг!" + +Создание расширения начинается с вызова макроса + +``` +PG_MODULE_MAGIC; +``` + +На этом магия не заканчивается, а только начинается. + +// сам макрос создает функцию проверяющую совместимость подгружаемого расширения с ядрос PostgreSQL + +// текст макроса можно прочитать в `src/include/fmgr.h` но это для джедаев + +### Аргументы + +Вспоминаем функцию из предыдущей лекции + +``` +Datum +my_get_two(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT32(2); +} +``` + +Макрос `PG_FUNCTION_ARGS` разворачивается в + +``` +/* Standard parameter list for fmgr-compatible functions */ +#define PG_FUNCTION_ARGS FunctionCallInfo fcinfo +``` +см. `src/include/fmgr.h` + +--- +Структура `FunctionCallInfo` имеет развесистую структуру содержит информацию о параметрах переданных в pg-функцию, пользоваться ей напрямую затруднительно (если ты не джедай темной стороны силы) + +Но есть специальный набор макросов для удобной работы с аргументами pg-функции + +--- + +Пример использования аргумента + +``` +#include "postgres.h" +#include "fmgr.h" + +PG_FUNCTION_INFO_V1(warn_me); + +Datum +warn_me(PG_FUNCTION_ARGS) +{ + int32 n = PG_GETARG_INT32(0); + elog(WARNING, "Предупреждаю: %i", n); + PG_RETURN_INT32(n); +} +``` + +``` +CREATE FUNCTION warn_me(int) RETURNS int +AS 'MODULE_PATHNAME', 'warn_me' +LANGUAGE C; +``` + +Мы видим что макром `PG_GETARG_INT32` используется для получения первого аргумента. +И этот аргумент сразу приводится к типу `int32` + +``` +# select warn_me(12); +WARNING: Предупреждаю: 12 + warn_me +--------- + 12 +(1 row) +``` + +--- + +Посмотрим на реализацию `PG_GETARG_INT32` в `src/include/fmgr.h`: + +``` +/* Macros for fetching arguments of standard types */ + +#define PG_GETARG_DATUM(n) (fcinfo->args[n].value) +#define PG_GETARG_INT32(n) DatumGetInt32(PG_GETARG_DATUM(n)) +#define PG_GETARG_UINT32(n) DatumGetUInt32(PG_GETARG_DATUM(n)) +#define PG_GETARG_INT16(n) DatumGetInt16(PG_GETARG_DATUM(n)) +#define PG_GETARG_UINT16(n) DatumGetUInt16(PG_GETARG_DATUM(n)) +#define PG_GETARG_CHAR(n) DatumGetChar(PG_GETARG_DATUM(n)) +#define PG_GETARG_BOOL(n) DatumGetBool(PG_GETARG_DATUM(n)) +``` + +Тут мы видим что как и все ее близницы братья `PG_GETARG_INT32` суммарно обращается к струкуре `fcinfo` о которой говорилось выше. + +Так же если мы проведем некоторое исследование мы узнаем что выражение `fcinfo->args[n].value` имеет тип `Datum`. + +И по всей видимости функция `DatumGetInt32` преобразует этот мифический пока для нас `Datum` к типу `int32`. + +К ним мы вернемся позже. + +(\*) задача со звездочкой: убедитесь самостоятельно что `fcinfo->args[n].value` имеет тип Datum + +--- + +Если мы обратим свой взор к макросу `PG_RETURN_INT32` в том же `src/include/fmgr.h` то там увидем схожую картину + +``` +/* Macros for returning results of standard types */ + +#define PG_RETURN_DATUM(x) return (x) +#define PG_RETURN_INT32(x) return Int32GetDatum(x) +#define PG_RETURN_UINT32(x) return UInt32GetDatum(x) +#define PG_RETURN_INT16(x) return Int16GetDatum(x) +#define PG_RETURN_UINT16(x) return UInt16GetDatum(x) +#define PG_RETURN_CHAR(x) return CharGetDatum(x) +#define PG_RETURN_BOOL(x) return BoolGetDatum(x) +``` + +Только тут направление преобразование другое `Int32GetDatum` из `int32` в `Datum` + +--- + +Так что же такое Datum? + +`src/include/postgres.h` + + +``` +/* + * A Datum contains either a value of a pass-by-value type or a pointer to a + * value of a pass-by-reference type. Therefore, we require: + * + * sizeof(Datum) == sizeof(void *) == 4 or 8 + * + * The functions below and the analogous functions for other types should be used to + * convert between a Datum and the appropriate C type. + */ + +typedef uintptr_t Datum; +``` + +`man uintptr_t`: + +`uintptr_t` is an unsigned integer type such that any valid (void *) value can be converted to this type and then converted back. + +Т.е. по сути это "машинное слово" определяемое разрядностью архитектуры. +--- + +В случае если размер данных позволяет, значение помещается в само "машинное слово". +В случае если размеры данных выходят за рамки "машииного слова", данные размещаются в опертивной памяти а в переменную типа Datum помещается указатель на них. + +`src/include/postgres.h` + +``` +/* + * DatumGetInt32 + * Returns 32-bit integer value of a datum. + */ +static inline int32 +DatumGetInt32(Datum X) +{ + return (int32) X; +} +``` + +``` +/* + * Int32GetDatum + * Returns datum representation for a 32-bit integer. + */ +static inline Datum +Int32GetDatum(int32 X) +{ + return (Datum) X; +} +``` + +Т.е. тут мы просто явно приводим тип "машинного слова" к требуемому, ничего более + +(***) Задача с тремя звездочками: поразмышляйте, почему `DatumGetInt32` реализована как intine функция, а не как макрос + +--- + +С хранением сложных типов данных в Datum мы будем резбираться на следующей лекции. + +А пока поиграем со стандартными типами + +``` +#include "postgres.h" +#include "fmgr.h" + +PG_FUNCTION_INFO_V1(my_factorial); + +Datum +my_factorial(PG_FUNCTION_ARGS) +{ + int32 res, n = PG_GETARG_INT32(0); + Datum d; + + if (n < 0) + elog(ERROR, "Так нельзя!"); + + if (n == 0) + PG_RETURN_INT32(1); + + d = DirectFunctionCall1(my_factorial, Int32GetDatum(n - 1)); + + res = DatumGetInt32(d) * n; + + PG_RETURN_INT32(res); +} +``` + +(*) Задача со звездочкой: Посмотрите на реализацию вызова `DirectFunctionCall1`, как она устроена внутри + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/README.md b/slides/2025 - Becoming PosgtreSQL Core Developer/README.md new file mode 100644 index 0000000..815904e --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/README.md @@ -0,0 +1,19 @@ +# Курс лекций "Как стать разработчиком PostgreSQL" + +Данный курс предназначен для начинающих разработчиков еще не погрузившихся в мир системного программирования в общем и не знакомых с внутреннем устройством PostgreSQL в частности. +В рамках курса учащийся двигаясь от простого к сложному познакомится с кодом СУБД PostgreSQL, с основными структурами и абстракциями используемыми в коде, а так же с приемами программирования применяющимися при разработки ядра PostgreSQL. +Курс предполагает решение большого количества простых учебных задач затрагивающих разные аспекты функционирования ядра PostgreSQL, с подробным изучением исходного кода ядра реализующего изучаемую функциональность. +В идеале после завершения курса учащийся должен свободно ориентироваться в большей части кода ядра PostgreSQL или уметь самостоятельно разобраться с теми частями, которые затронуты не были. + +Данный курс не предполагает углубленного знакомства с техникой и алгоритмикой хранения поиска и обработки данных, но предполагает подробное знакомство с кодовой инфраструктурой в рамках которой эти алгоритмы практически реализованы. + +Курс находится на ранних этапах разработки. +На данный момент готовы лекции: + +- Создание первого расширения PostgreSQL +- Базовые структуры PostgreSQL: Регистровые типы данных + +В процессе создания находится лекция: + +- Базовые структуры PostgreSQL: Типы данных переменной длинны + diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.odp b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.odp deleted file mode 100644 index c7faadb..0000000 Binary files a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.odp and /dev/null differ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.pdf b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.pdf deleted file mode 100644 index e5a329d..0000000 Binary files a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - Creating own extension, Nepal/Creating_extension_2025.pdf and /dev/null differ diff --git "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" "b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" deleted file mode 100644 index 6c04d17..0000000 Binary files "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" and /dev/null differ diff --git "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" "b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" deleted file mode 100644 index 6ee00ce..0000000 Binary files "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\230\320\242\320\234\320\236, \320\222\320\250\320\255/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" and /dev/null differ diff --git "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" "b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" deleted file mode 100644 index 58133f2..0000000 Binary files "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.odp" and /dev/null differ diff --git "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" "b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" deleted file mode 100644 index 07f2634..0000000 Binary files "a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-08 - \320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217, \320\255\320\273\320\270\321\201\321\202\320\260/\320\241\320\276\320\267\320\264\320\260\320\275\320\270\320\265 \321\201\320\276\320\261\321\201\321\202\320\262\320\265\320\275\320\275\320\276\320\263\320\276 \321\200\320\260\321\201\321\210\320\270\321\200\320\265\320\275\320\270\321\217-2025.pdf" and /dev/null differ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-10 - Creating own extension, Nepal/Creating_extension_2025.odp b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-10 - Creating own extension, Nepal/Creating_extension_2025.odp deleted file mode 100644 index 42b45d0..0000000 Binary files a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/2025-10 - Creating own extension, Nepal/Creating_extension_2025.odp and /dev/null differ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/README.md b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/README.md deleted file mode 100644 index ca496a5..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/README.md +++ /dev/null @@ -1,10 +0,0 @@ -### Аннотация - -#### Создание расширения PostgreSQL -#### Первый шаг на пути к разработке ядра postgres. - -Популярность PostgreSQL обеспечивается не только ее производительностью и доступностью, но во многом своим открытым процессом разработки: исходный код СУБД доступен для изучения и модификации, и любой желающий может принять участие в разработке ядра проекта, предлагая свое улучшения и изменения. -Программист для того чтобы стать ядра разработчиком ядра PostgreSQL должен пройти длинный путь, но практически каждый начинает свое движение с разработки расширения PostgreSQL. -PostgreSQL предоставляет широкие возможности по расширению функциональности и модификации поведения ядра СУБД через механизм расширений. - -В этой лекции мы рассмотрим основы создания расширений: что это такое, из каких элементов оно состоит, и создадим первое учебное расширение. diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/log.log b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/log.log deleted file mode 100644 index 5832a3c..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/log.log +++ /dev/null @@ -1,361 +0,0 @@ -Extension is a set of PostgreSQL objects that can be `CREATE`ed. -Like `CREATE FUNCTION`, `CREATE TYPE` or `CREATE OPERATOR`. -This set is created, updated and deleted as a bundle. -When you do `CREATE EXTENSION` you it will create all object included into extension. -When you do `DROP EXTENSION` all that objects will be automatically removed. - -So extension is just a set of SQL commands to create or update extension schema. -(You even do not need to delete it, `DROP EXTENSION` will delete them automatically) - -Functions may be written in `PL/pgSQL` or other `PL/*` or you can load binary function from shared `.so` library. -. -You can register a function as a hook handler to change behavior if PostgreSQL. - - - -See https://github.com/IshaanAdarsh/Postgres-extension-tutorial/blob/main/SGML/Main.md for more info - -``` - -$ whoami -nataraj - -$ sudo -u postgres createuser -s nataraj -``` - -Make sure that `-dev` files for postgres are installed. In Debian-based distributives it wil -be like this - -``` -sudo apt-get install postgresql-server-dev-all - -``` - - -``` -$ mkdir my_first_extension - -$ cd my_first_extension -``` - -``` -touch my_first_extension.control -``` - -``` -# my_first_extension.control -# Comment line to provide additional information about the extension -comment = 'My Very First Extension' - -# Specifies the default version of the extension -default_version = '0.0.1' -``` - -https://www.postgresql.org/docs/17/extend-extensions.html#EXTEND-EXTENSIONS-FILES - - ---- - -``` -touch my_first_extension--0.0.1.sql -``` - -``` -CREATE TABLE my_first_extension_table ( - id SERIAL PRIMARY KEY, - my_string VARCHAR NOT NULL -); - -INSERT INTO my_first_extension_table (my_string) VALUES('Hello, World'); -``` - ---- - -``` -touch Makefile -``` - -``` -EXTENSION = my_first_extension # Name of the extension -DATA = my_first_extension--0.0.1.sql # SQL file containing extension objects and functions - -PG_CONFIG ?= pg_config # Path to the pg_config executable -PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config -include $(PGXS) # Include the PostgreSQL Extension Makefile -``` - ---- - -``` -make -sudo make install -``` - -``` -sudo -u postgres psql - -# CREATE EXTENSION my_first_extension; -CREATE EXTENSION - -# SELECT * FROM my_first_extension_table; - id | my_string -----+-------------- - 1 | Hello, World -(1 row) - -# DROP EXTENSION my_first_extension; -DROP EXTENSION - -# SELECT * FROM my_first_extension_table; -ERROR: relation "my_first_extension_table" does not exist -СТРОКА 1: SELECT * FROM my_first_extension_table; - ^ -``` - ------------- - -# Add tests - -``` -mkdir sql -``` - -edit `sql/my_first_extension-main-test.sql` - -``` -CREATE EXTENSION my_first_extension; - -SELECT * FROM my_first_extension_table; - -DROP EXTENSION - --- There should be no my_first_extension_table anymore -SELECT * FROM my_first_extension_table; -``` - ----- - -change Makefile - -``` -EXTENSION = my_first_extension # Name of the extension -DATA = my_first_extension--0.0.1.sql # SQL file containing extension objects and functions -REGRESS = my_first_extension-main-test - - -PG_CONFIG ?= pg_config # Path to the pg_config executable -PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config -include $(PGXS) # Include the PostgreSQL Extension Makefile -``` - -run `make installcheck` - - -and get an error: `my_first_extension/expected/my_first_extension-main-test.out: No such file or directory` - -and a `results` dir. - ----- - -Check that `results/my_first_extension-main-test.out` is what you expect - -``` -$ cat results/my_first_extension-main-test.out -CREATE EXTENSION my_first_extension; -SELECT * FROM my_first_extension_table; - id | my_string -----+-------------- - 1 | Hello, World -(1 row) - -DROP EXTENSION --- There should be no my_first_extension_table anymore -SELECT * FROM my_first_extension_table; -ERROR: syntax error at or near "SELECT" -LINE 3: SELECT * FROM my_first_extension_table; - ^ -``` - ----- - -If everything as you expected copy `my_first_extension-main-test.out` from `results` dir to `expected` - -``` -mkdir expected -cp results/my_first_extension-main-test.out expected -``` - ----- - -Now tests should pass - -``` -n$ make installcheck -echo "+++ regress install-check in +++" && /usr/lib/postgresql/15/lib/pgxs/src/makefiles/../../src/test/regress/pg_regress --inputdir=./ --bindir='/usr/lib/postgresql/15/bin' --dbname=contrib_regression my_first_extension-main-test -+++ regress install-check in +++ -(using postmaster on Unix socket, default port) -============== dropping database "contrib_regression" ============== -SET -DROP DATABASE -============== creating database "contrib_regression" ============== -CREATE DATABASE -ALTER DATABASE -ALTER DATABASE -ALTER DATABASE -ALTER DATABASE -ALTER DATABASE -ALTER DATABASE -============== running regression test queries ============== -test my_first_extension-main-test ... ok 54 ms - -===================== - All 1 tests passed. -===================== -``` - ------ - -Now let's create create a new version of extension, with a plpsql function in it - -* Change version from `0.0.1` to `0.0.2` in `my_first_extension.control`: - -``` -default_version = '0.0.2' -``` - -* rename schema creation file from `my_first_extension--0.0.1.sql` to `my_first_extension--0.0.2.sql` -* create an schema update file `my_first_extension--0.0.1--0.0.2.sql` - -Add to both of them function creation code - -``` -CREATE FUNCTION my_one() -returns int -language plpgsql -as -$$ -begin - return 1; -end; -$$; - -``` - -* Update `Makefile` adding new sql file names to `DATA` variable - -``` -DATA = my_first_extension--0.0.2.sql my_first_extension--0.0.1--0.0.2.sql -``` - -* install extension - -``` -sudo make install - -``` - -* check everything works - -``` -$ sudo -u postgres psql - -=# CREATE EXTENSION my_first_extension; -CREATE EXTENSION - -s=# SELECT my_one(); - my_one --------- - 1 -(1 row) -``` - ----- - -Write test for `my_one` function yourself - ----- - -https://www.highgo.ca/2020/01/10/how-to-create-test-and-debug-an-extension-written-in-c-for-postgresql/ - - -Creating C-function - -// Do not forget to install `postgresql-server-dev-all` - -create `my_first_extension.c` file - -``` -#include "postgres.h" -#include "fmgr.h" - -PG_MODULE_MAGIC; - -PG_FUNCTION_INFO_V1(my_get_two); - -Datum -my_get_two(PG_FUNCTION_ARGS) -{ - PG_RETURN_INT32(2); -} -``` - -add following lines to `Makefile` - -``` -MODULE_big = my_first_extension -OBJS = my_first_extension.o - -``` -and to the `my_first_extension.control` - - -``` -module_pathname = '$libdir/my_first_extension' - -``` - - -Check everything works well by running - -``` -make -``` - -add to schema -``` -CREATE FUNCTION my_two() -RETURNS INT -AS 'MODULE_PATHNAME', 'my_get_two' -LANGUAGE C; -``` - - -bump version in *.sql files, Makefile and control file - - -``` -make -sudo make install -``` - -Check everything works: - -``` -$ sudo -u postgres psql - -=# DROP EXTENSION my_first_extension; -DROP EXTENSION - -=# CREATE EXTENSION my_first_extension; -CREATE EXTENSION -postgres=# SELECT my_two(); - my_two --------- - 2 -(1 row) - -``` - -Do not forget to write tests! - - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/Makefile b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/Makefile deleted file mode 100644 index 4b14455..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -MODULE_big = my_first_extension -EXTENSION = my_first_extension # Name of the extension -DATA = my_first_extension--0.0.3.sql my_first_extension--0.0.1--0.0.2.sql my_first_extension--0.0.2--0.0.3.sql -REGRESS = my_first_extension-main-test - -OBJS = my_first_extension.o - - -PG_CONFIG ?= pg_config # Path to the pg_config executable -PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config -include $(PGXS) # Include the PostgreSQL Extension Makefile - - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/expected/my_first_extension-main-test.out b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/expected/my_first_extension-main-test.out deleted file mode 100644 index a0b8cc9..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/expected/my_first_extension-main-test.out +++ /dev/null @@ -1,13 +0,0 @@ -CREATE EXTENSION my_first_extension; -SELECT * FROM my_first_extension_table; - id | my_string -----+-------------- - 1 | Hello, World -(1 row) - -DROP EXTENSION my_first_extension; --- There should be no my_first_extension_table anymore -SELECT * FROM my_first_extension_table; -ERROR: relation "my_first_extension_table" does not exist -LINE 1: SELECT * FROM my_first_extension_table; - ^ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.1--0.0.2.sql b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.1--0.0.2.sql deleted file mode 100644 index 9c107ac..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.1--0.0.2.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE FUNCTION my_one() -returns int -language plpgsql -as -$$ -begin - return 1; -end; -$$; - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.2--0.0.3.sql b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.2--0.0.3.sql deleted file mode 100644 index 7b9adcd..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.2--0.0.3.sql +++ /dev/null @@ -1,5 +0,0 @@ -CREATE FUNCTION my_two() -RETURNS INT -AS 'MODULE_PATHNAME', 'my_get_two' -LANGUAGE C; - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.3.sql b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.3.sql deleted file mode 100644 index b25f223..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension--0.0.3.sql +++ /dev/null @@ -1,24 +0,0 @@ -CREATE TABLE my_first_extension_table ( - id SERIAL PRIMARY KEY, - my_string VARCHAR NOT NULL -); - -INSERT INTO my_first_extension_table (my_string) VALUES('Hello, World'); - - -CREATE FUNCTION my_one() -returns int -language plpgsql -as -$$ -begin - return 1; -end; -$$; - - -CREATE FUNCTION my_two() -RETURNS INT -AS 'MODULE_PATHNAME', 'my_get_two' -LANGUAGE C; - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension.c b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension.c deleted file mode 100644 index a126494..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "postgres.h" -#include "fmgr.h" - -PG_MODULE_MAGIC; - -PG_FUNCTION_INFO_V1(my_get_two); - -Datum -my_get_two(PG_FUNCTION_ARGS) -{ - PG_RETURN_INT32(2); -} diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension.control b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension.control deleted file mode 100644 index 68688a0..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/my_first_extension.control +++ /dev/null @@ -1,8 +0,0 @@ -# my_first_extension.control -# Comment line to provide additional information about the extension -comment = 'My Very First Extension' - -# Specifies the default version of the extension -default_version = '0.0.3' -module_pathname = '$libdir/my_first_extension' - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/sql/my_first_extension-main-test.sql b/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/sql/my_first_extension-main-test.sql deleted file mode 100644 index 8992652..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 1. Creating own extension/code/my_first_extension/sql/my_first_extension-main-test.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE EXTENSION my_first_extension; - -SELECT * FROM my_first_extension_table; - -DROP EXTENSION my_first_extension; - --- There should be no my_first_extension_table anymore -SELECT * FROM my_first_extension_table; - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/2025 - Basic Structures - Register Data Types - Eng/basic_structures-2025.odp b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/2025 - Basic Structures - Register Data Types - Eng/basic_structures-2025.odp deleted file mode 100644 index e42e7be..0000000 Binary files a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/2025 - Basic Structures - Register Data Types - Eng/basic_structures-2025.odp and /dev/null differ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/basic_structures-2025.odp b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/basic_structures-2025.odp deleted file mode 100644 index 256f122..0000000 Binary files a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/basic_structures-2025.odp and /dev/null differ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/basic_structures-2025.pdf b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/basic_structures-2025.pdf deleted file mode 100644 index 0fcab67..0000000 Binary files a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/basic_structures-2025.pdf and /dev/null differ diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/Makefile b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/Makefile deleted file mode 100644 index 6ccf984..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -MODULE_big = data_types_examples -EXTENSION = data_types_examples # Name of the extension -DATA = data_types_examples--0.0.1.sql -# REGRESS = my_first_extension-main-test - -OBJS = data_types_examples.o warn_me.o my_factorial.o hello_world.o - - -PG_CONFIG ?= pg_config # Path to the pg_config executable -PGXS := $(shell $(PG_CONFIG) --pgxs) # Get the PostgreSQL Extension Makefile from pg_config -include $(PGXS) # Include the PostgreSQL Extension Makefile - - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql deleted file mode 100644 index e6e370a..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql +++ /dev/null @@ -1,17 +0,0 @@ - - -CREATE FUNCTION warn_me(int) RETURNS int -AS 'MODULE_PATHNAME', 'warn_me' -LANGUAGE C; - - -CREATE FUNCTION my_factorial(int) RETURNS int -AS 'MODULE_PATHNAME', 'my_factorial' -LANGUAGE C; - - -CREATE FUNCTION hello_world() -RETURNS TEXT -AS 'MODULE_PATHNAME', 'hello_world' -LANGUAGE C; - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c deleted file mode 100644 index e53bb30..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "postgres.h" -#include "fmgr.h" - -PG_MODULE_MAGIC; - -PG_FUNCTION_INFO_V1(my_inc); - -Datum -my_inc(PG_FUNCTION_ARGS) -{ - - PG_RETURN_INT32(2); -} diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control deleted file mode 100644 index 99d98e9..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control +++ /dev/null @@ -1,8 +0,0 @@ -# my_first_extension.control -# Comment line to provide additional information about the extension -comment = 'Data Types Exampls' - -# Specifies the default version of the extension -default_version = '0.0.1' -module_pathname = '$libdir/data_types_examples' - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/hello_world.c b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/hello_world.c deleted file mode 100644 index 34e079f..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/hello_world.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "postgres.h" -#include "fmgr.h" -#include "utils/builtins.h" - -PG_FUNCTION_INFO_V1(hello_world); - -Datum -hello_world(PG_FUNCTION_ARGS) -{ - char message[] = "Hello, World!"; - Datum datum; - - datum = CStringGetTextDatum(message); - - PG_RETURN_TEXT_P(datum); -} - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c deleted file mode 100644 index 2e60743..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "postgres.h" -#include "fmgr.h" - -PG_FUNCTION_INFO_V1(my_factorial); - -Datum -my_factorial(PG_FUNCTION_ARGS) -{ - int32 res, n = PG_GETARG_INT32(0); - Datum d; - - if (n < 0) - elog(ERROR, "Так нельзя!"); - - if (n == 0) - PG_RETURN_INT32(1); - - d = DirectFunctionCall1(my_factorial, Int32GetDatum(n - 1)); - - res = DatumGetInt32(d) * n; - - PG_RETURN_INT32(res); -} - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c deleted file mode 100644 index 4da0231..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "postgres.h" -#include "fmgr.h" - -PG_FUNCTION_INFO_V1(warn_me); - -Datum -warn_me(PG_FUNCTION_ARGS) -{ - int32 n = PG_GETARG_INT32(0); - elog(WARNING, "Предупреждаю: %i", n); - PG_RETURN_INT32(n); -} - diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/log.md b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/log.md deleted file mode 100644 index c07b876..0000000 --- a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/log.md +++ /dev/null @@ -1,247 +0,0 @@ - -* Свободное ПО замечательно тем, что всегда можно самому посмтреть как и что устроено - -*Сеанс белой магии с разоблачениями* - -Не только знания о структуре, но и навыки работы с кодом - - -## Стандартные арифметические типы - -Исторические причины: - -* Postgres95 моложе С99 -* Сколько байт займет `signed i;` ? - -Поэтому: - -``` -/* Historical names for types in . */ -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; -``` -`src/include/c.h` - -## Волшебные макросы pg-функций - -"С-Программист, помни! Макрос -- твой лучший друг!" - -Создание расширения начинается с вызова макроса - -``` -PG_MODULE_MAGIC; -``` - -На этом магия не заканчивается, а только начинается. - -// сам макрос создает функцию проверяющую совместимость подгружаемого расширения с ядрос PostgreSQL - -// текст макроса можно прочитать в `src/include/fmgr.h` но это для джедаев - -### Аргументы - -Вспоминаем функцию из предыдущей лекции - -``` -Datum -my_get_two(PG_FUNCTION_ARGS) -{ - PG_RETURN_INT32(2); -} -``` - -Макрос `PG_FUNCTION_ARGS` разворачивается в - -``` -/* Standard parameter list for fmgr-compatible functions */ -#define PG_FUNCTION_ARGS FunctionCallInfo fcinfo -``` -см. `src/include/fmgr.h` - ---- -Структура `FunctionCallInfo` имеет развесистую структуру содержит информацию о параметрах переданных в pg-функцию, пользоваться ей напрямую затруднительно (если ты не джедай темной стороны силы) - -Но есть специальный набор макросов для удобной работы с аргументами pg-функции - ---- - -Пример использования аргумента - -``` -#include "postgres.h" -#include "fmgr.h" - -PG_FUNCTION_INFO_V1(warn_me); - -Datum -warn_me(PG_FUNCTION_ARGS) -{ - int32 n = PG_GETARG_INT32(0); - elog(WARNING, "Предупреждаю: %i", n); - PG_RETURN_INT32(n); -} -``` - -``` -CREATE FUNCTION warn_me(int) RETURNS int -AS 'MODULE_PATHNAME', 'warn_me' -LANGUAGE C; -``` - -Мы видим что макром `PG_GETARG_INT32` используется для получения первого аргумента. -И этот аргумент сразу приводится к типу `int32` - -``` -# select warn_me(12); -WARNING: Предупреждаю: 12 - warn_me ---------- - 12 -(1 row) -``` - ---- - -Посмотрим на реализацию `PG_GETARG_INT32` в `src/include/fmgr.h`: - -``` -/* Macros for fetching arguments of standard types */ - -#define PG_GETARG_DATUM(n) (fcinfo->args[n].value) -#define PG_GETARG_INT32(n) DatumGetInt32(PG_GETARG_DATUM(n)) -#define PG_GETARG_UINT32(n) DatumGetUInt32(PG_GETARG_DATUM(n)) -#define PG_GETARG_INT16(n) DatumGetInt16(PG_GETARG_DATUM(n)) -#define PG_GETARG_UINT16(n) DatumGetUInt16(PG_GETARG_DATUM(n)) -#define PG_GETARG_CHAR(n) DatumGetChar(PG_GETARG_DATUM(n)) -#define PG_GETARG_BOOL(n) DatumGetBool(PG_GETARG_DATUM(n)) -``` - -Тут мы видим что как и все ее близницы братья `PG_GETARG_INT32` суммарно обращается к струкуре `fcinfo` о которой говорилось выше. - -Так же если мы проведем некоторое исследование мы узнаем что выражение `fcinfo->args[n].value` имеет тип `Datum`. - -И по всей видимости функция `DatumGetInt32` преобразует этот мифический пока для нас `Datum` к типу `int32`. - -К ним мы вернемся позже. - -(\*) задача со звездочкой: убедитесь самостоятельно что `fcinfo->args[n].value` имеет тип Datum - ---- - -Если мы обратим свой взор к макросу `PG_RETURN_INT32` в том же `src/include/fmgr.h` то там увидем схожую картину - -``` -/* Macros for returning results of standard types */ - -#define PG_RETURN_DATUM(x) return (x) -#define PG_RETURN_INT32(x) return Int32GetDatum(x) -#define PG_RETURN_UINT32(x) return UInt32GetDatum(x) -#define PG_RETURN_INT16(x) return Int16GetDatum(x) -#define PG_RETURN_UINT16(x) return UInt16GetDatum(x) -#define PG_RETURN_CHAR(x) return CharGetDatum(x) -#define PG_RETURN_BOOL(x) return BoolGetDatum(x) -``` - -Только тут направление преобразование другое `Int32GetDatum` из `int32` в `Datum` - ---- - -Так что же такое Datum? - -`src/include/postgres.h` - - -``` -/* - * A Datum contains either a value of a pass-by-value type or a pointer to a - * value of a pass-by-reference type. Therefore, we require: - * - * sizeof(Datum) == sizeof(void *) == 4 or 8 - * - * The functions below and the analogous functions for other types should be used to - * convert between a Datum and the appropriate C type. - */ - -typedef uintptr_t Datum; -``` - -`man uintptr_t`: - -`uintptr_t` is an unsigned integer type such that any valid (void *) value can be converted to this type and then converted back. - -Т.е. по сути это "машинное слово" определяемое разрядностью архитектуры. ---- - -В случае если размер данных позволяет, значение помещается в само "машинное слово". -В случае если размеры данных выходят за рамки "машииного слова", данные размещаются в опертивной памяти а в переменную типа Datum помещается указатель на них. - -`src/include/postgres.h` - -``` -/* - * DatumGetInt32 - * Returns 32-bit integer value of a datum. - */ -static inline int32 -DatumGetInt32(Datum X) -{ - return (int32) X; -} -``` - -``` -/* - * Int32GetDatum - * Returns datum representation for a 32-bit integer. - */ -static inline Datum -Int32GetDatum(int32 X) -{ - return (Datum) X; -} -``` - -Т.е. тут мы просто явно приводим тип "машинного слова" к требуемому, ничего более - -(***) Задача с тремя звездочками: поразмышляйте, почему `DatumGetInt32` реализована как intine функция, а не как макрос - ---- - -С хранением сложных типов данных в Datum мы будем резбираться на следующей лекции. - -А пока поиграем со стандартными типами - -``` -#include "postgres.h" -#include "fmgr.h" - -PG_FUNCTION_INFO_V1(my_factorial); - -Datum -my_factorial(PG_FUNCTION_ARGS) -{ - int32 res, n = PG_GETARG_INT32(0); - Datum d; - - if (n < 0) - elog(ERROR, "Так нельзя!"); - - if (n == 0) - PG_RETURN_INT32(1); - - d = DirectFunctionCall1(my_factorial, Int32GetDatum(n - 1)); - - res = DatumGetInt32(d) * n; - - PG_RETURN_INT32(res); -} -``` - -(*) Задача со звездочкой: Посмотрите на реализацию вызова `DirectFunctionCall1`, как она устроена внутри -