From: Nikolay Shaplov Date: Fri, 19 Dec 2025 15:28:53 +0000 (+0300) Subject: Третяя лекция, про varlen типы данных X-Git-Url: http://gitweb.nataraj.world/?a=commitdiff_plain;h=2dd56629ce95f37806181607b48586dffd69579f;p=articles.git Третяя лекция, про varlen типы данных --- diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/basic_structures-varlen-2025.odp b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/basic_structures-varlen-2025.odp new file mode 100644 index 0000000..e34c86b Binary files /dev/null and b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/basic_structures-varlen-2025.odp differ diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/log b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/log new file mode 100644 index 0000000..073dbc7 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/log @@ -0,0 +1,91 @@ + +Вспоминаем наш пример с прошлой лекции. + + +Datum +hello_world(PG_FUNCTION_ARGS) +{ + char message[] = "Hello, World!"; + Datum datum; + + datum = CStringGetTextDatum(message); + + PG_RETURN_TEXT_P(datum); +} + +Попробуем разобраться как устроено хранение не-регистровых данных + +Попробуем зайти со стороны PG_RETURN_TEXT_P + +Находим в src/include/fmgr.h + +/* RETURN macros for other pass-by-ref types will typically look like this: */ +#define PG_RETURN_BYTEA_P(x) PG_RETURN_POINTER(x) +#define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x) +#define PG_RETURN_BPCHAR_P(x) PG_RETURN_POINTER(x) +#define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x) + + +Не очень интересно, он просто возвращает указатель. +(По ветке PG_RETURN_POINTER сходите сами) + +Посмотрим на функцию CStringGetTextDatum где данные лежащие по этому указателю конструируются. + +Находим + +#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s)) + +В src/include/utils/builtins.h + +Это уже интереснее. + +Ищем cstring_to_text + +Находим в src/backend/utils/adt/varlena.c + +/* + * cstring_to_text + * + * Create a text value from a null-terminated C string. + * + * The new text value is freshly palloc'd with a full-size VARHDR. + */ +text * +cstring_to_text(const char *s) +{ + return cstring_to_text_with_len(s, strlen(s)); +} + + +И чуть ниже + +/* + * cstring_to_text_with_len + * + * Same as cstring_to_text except the caller specifies the string length; + * the string need not be null_terminated. + */ +text * +cstring_to_text_with_len(const char *s, int len) +{ + text *result = (text *) palloc(len + VARHDRSZ); + + SET_VARSIZE(result, len + VARHDRSZ); + memcpy(VARDATA(result), s, len); + + return result; +} + +"Добрались, добрались, повезло, повезло" + +Что тут происходит: + +1. Резервируем память на VARHDRSZ больше чем динна строки + +2. Вызываем некий макрос SET_VARSIZE передавая ему вновь созданный объект и его полную длинну + +3. Копируем в объект содержимое строки начиная с позиции VARDATA(result) + + + + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/Makefile b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/Makefile new file mode 100644 index 0000000..153d680 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/Makefile @@ -0,0 +1,13 @@ +MODULE_big = varlen_examples +EXTENSION = varlen_examples # Name of the extension +DATA = varlen_examples--0.0.1.sql +# REGRESS = my_first_extension-main-test + +OBJS = 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/3. Basic Structures: Variable Length Data/src/masterclass_seed/hello_world.c b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/hello_world.c new file mode 100644 index 0000000..71c2e2d --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/hello_world.c @@ -0,0 +1,18 @@ +#include "postgres.h" +#include "fmgr.h" +#include "utils/builtins.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(hello_world); + +Datum +hello_world(PG_FUNCTION_ARGS) +{ + char message[] = "Hello, World!"; /* 13 символов */ + Datum datum; + + datum = CStringGetTextDatum(message); + + PG_RETURN_DATUM(datum); +} diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/varlen_examples--0.0.1.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/varlen_examples--0.0.1.sql new file mode 100644 index 0000000..e943fa2 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/varlen_examples--0.0.1.sql @@ -0,0 +1,7 @@ + + +CREATE FUNCTION hello_world() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world' +LANGUAGE C; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/varlen_examples.control b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/varlen_examples.control new file mode 100644 index 0000000..188300c --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/masterclass_seed/varlen_examples.control @@ -0,0 +1,8 @@ +# my_first_extension.control +# Comment line to provide additional information about the extension +comment = 'VarLen Types Exampls' + +# Specifies the default version of the extension +default_version = '0.0.1' +module_pathname = '$libdir/varlen_examples' + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/Makefile b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/Makefile new file mode 100644 index 0000000..153d680 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/Makefile @@ -0,0 +1,13 @@ +MODULE_big = varlen_examples +EXTENSION = varlen_examples # Name of the extension +DATA = varlen_examples--0.0.1.sql +# REGRESS = my_first_extension-main-test + +OBJS = 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/3. Basic Structures: Variable Length Data/src/varlen_examples/hello_world.c b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/hello_world.c new file mode 100644 index 0000000..560bd6a --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/hello_world.c @@ -0,0 +1,119 @@ +#include "postgres.h" +#include "fmgr.h" +#include "utils/builtins.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(hello_world); + +Datum +hello_world(PG_FUNCTION_ARGS) +{ + char message[] = "Hello, World!"; /* 13 символов */ + Datum datum; + + datum = CStringGetTextDatum(message); + + PG_RETURN_DATUM(datum); +} + +PG_FUNCTION_INFO_V1(hello_world2); +Datum +hello_world2(PG_FUNCTION_ARGS) +{ + char message[] = "Hello, World!"; /* 13 символов */ + int i; + Datum datum; + + datum = CStringGetTextDatum(message); + + for(i = 0; i < 10; i++) + printf("%02X ", ((unsigned char*) datum)[i]); + printf("\n"); + + PG_RETURN_DATUM(datum); +} + +PG_FUNCTION_INFO_V1(hello_world3); +Datum +hello_world3(PG_FUNCTION_ARGS) +{ + char message[] = "Hello, World!"; /* 13 символов */ + int i; + Datum datum; + + datum = CStringGetTextDatum(message); + + for(i = 0; i < 10; i++) + fprintf(stderr, "%02X ", ((unsigned char*) datum)[i]); + fprintf(stderr, "\n"); + + PG_RETURN_DATUM(datum); +} + +PG_FUNCTION_INFO_V1(hello_world4); +Datum +hello_world4(PG_FUNCTION_ARGS) +{ + char message[] = "01234567890123456789"; /* 20 символов */ + int i; + Datum datum; + + datum = CStringGetTextDatum(message); + + for(i = 0; i < 36; i++) + fprintf(stderr, "%02X ", ((unsigned char*) datum)[i]); + fprintf(stderr, "\n"); + + PG_RETURN_DATUM(datum); +} + +char * dump_buf_to_hex_cstring(char * buf, int len); + +char * +dump_buf_to_hex_cstring(char * buf, int len) +{ + char *res, *p; + int i; + int print_len = len < 16 ? len : 16; + + res = palloc(print_len * 3 + 1 + 1); /* По три байта на символ (две цифры и пробел), \n и \0 */ + p = res; + for(i=0; i< print_len; i++) + { + p += sprintf(p, "%02X ", (unsigned char) *buf); + buf++; + } + sprintf(p, "\n"); + + return(res); +} + + +#include"varatt.h" + +PG_FUNCTION_INFO_V1(hello_world5); +Datum +hello_world5(PG_FUNCTION_ARGS) +{ + char message[] = "01234567890123456789"; /* 20 символов */ + Datum datum; + + datum = CStringGetTextDatum(message); + + elog(WARNING, "%s", dump_buf_to_hex_cstring((char*)datum, VARSIZE(datum))); + + PG_RETURN_DATUM(datum); +} + +PG_FUNCTION_INFO_V1(dump_text_datum); +Datum +dump_text_datum(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + + elog(WARNING, "%s", dump_buf_to_hex_cstring((char*)txt, VARSIZE(txt))); + + PG_RETURN_TEXT_P(txt); +} + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/varlen_examples--0.0.1.sql b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/varlen_examples--0.0.1.sql new file mode 100644 index 0000000..a29da95 --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/varlen_examples--0.0.1.sql @@ -0,0 +1,32 @@ + + +CREATE FUNCTION hello_world() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world' +LANGUAGE C; + +CREATE FUNCTION hello_world2() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world2' +LANGUAGE C; + +CREATE FUNCTION hello_world3() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world3' +LANGUAGE C; + +CREATE FUNCTION hello_world4() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world4' +LANGUAGE C; + +CREATE FUNCTION hello_world5() +RETURNS TEXT +AS 'MODULE_PATHNAME', 'hello_world5' +LANGUAGE C; + +CREATE FUNCTION dump_text_datum(TEXT) +RETURNS TEXT +AS 'MODULE_PATHNAME', 'dump_text_datum' +LANGUAGE C; + diff --git a/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/varlen_examples.control b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/varlen_examples.control new file mode 100644 index 0000000..188300c --- /dev/null +++ b/slides/2025 - Becoming PosgtreSQL Core Developer/3. Basic Structures: Variable Length Data/src/varlen_examples/varlen_examples.control @@ -0,0 +1,8 @@ +# my_first_extension.control +# Comment line to provide additional information about the extension +comment = 'VarLen Types Exampls' + +# Specifies the default version of the extension +default_version = '0.0.1' +module_pathname = '$libdir/varlen_examples' +