]> Untitled Git - articles.git/commitdiff
Зачатки лекции про типы данных
authorNikolay Shaplov <dhyan@nataraj.su>
Thu, 7 Aug 2025 14:25:21 +0000 (17:25 +0300)
committerNikolay Shaplov <dhyan@nataraj.su>
Thu, 7 Aug 2025 14:25:21 +0000 (17:25 +0300)
14 files changed:
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/Makefile [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples--0.0.1.sql [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.bc [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.c [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.control [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.o [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.so [new file with mode: 0755]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.bc [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.c [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.o [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.bc [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.c [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.o [new file with mode: 0644]
slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/log.md [new file with mode: 0644]

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
new file mode 100644 (file)
index 0000000..f3bc8f7
--- /dev/null
@@ -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
+
+
+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
new file mode 100644 (file)
index 0000000..bbd5d55
--- /dev/null
@@ -0,0 +1,15 @@
+
+CREATE FUNCTION my_inc()
+RETURNS INT
+AS 'MODULE_PATHNAME', 'my_inc'
+LANGUAGE C;
+
+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;
+
diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.bc b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.bc
new file mode 100644 (file)
index 0000000..7978b75
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.bc differ
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
new file mode 100644 (file)
index 0000000..e53bb30
--- /dev/null
@@ -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 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
new file mode 100644 (file)
index 0000000..99d98e9
--- /dev/null
@@ -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 Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.o b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.o
new file mode 100644 (file)
index 0000000..adbe744
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.o differ
diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.so b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.so
new file mode 100755 (executable)
index 0000000..0ff0684
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/data_types_examples.so differ
diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.bc b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.bc
new file mode 100644 (file)
index 0000000..42a2409
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.bc differ
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
new file mode 100644 (file)
index 0000000..2e60743
--- /dev/null
@@ -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 Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.o b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.o
new file mode 100644 (file)
index 0000000..e0852f0
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/my_factorial.o differ
diff --git a/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.bc b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.bc
new file mode 100644 (file)
index 0000000..33a0e4f
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.bc differ
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
new file mode 100644 (file)
index 0000000..4da0231
--- /dev/null
@@ -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 Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.o b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.o
new file mode 100644 (file)
index 0000000..3a1d04c
Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Developer. 2. Basic Structures: Register Data Types/src/data_types_examples/warn_me.o differ
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
new file mode 100644 (file)
index 0000000..f32f1bd
--- /dev/null
@@ -0,0 +1,245 @@
+
+* Свободное ПО замечательно тем, что всегда можно самому посмтреть как и что устроено
+
+*Сеанс белой магии с разоблачениями*
+
+Не только знания о структуре, но и навыки работы с кодом
+
+
+## Стандартные арифметические типы
+
+Исторические причины:
+
+* Postgres95 моложе С99
+* Сколько байт займет `signed i;` ?
+
+Поэтому:
+
+```
+/* Historical names for types in <stdint.h>. */
+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`, как она устроена внутри
+