--- /dev/null
+
+Вспоминаем наш пример с прошлой лекции.
+
+
+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)
+
+
+
+
--- /dev/null
+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
+
+
--- /dev/null
+#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);
+}
--- /dev/null
+
+
+CREATE FUNCTION hello_world()
+RETURNS TEXT
+AS 'MODULE_PATHNAME', 'hello_world'
+LANGUAGE C;
+
--- /dev/null
+# 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'
+
--- /dev/null
+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
+
+
--- /dev/null
+#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);
+}
+
--- /dev/null
+
+
+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;
+
--- /dev/null
+# 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'
+