38.12. ÐолÑзоваÑелÑÑкие ÑипÑ
Ðак опиÑÑвалоÑÑ Ð² Разделе 38.2, PostgreSQL Ð¼Ð¾Ð¶ÐµÑ ÑаÑÑиÑÑÑÑÑÑ Ð¸ поддеÑживаÑÑ Ð½Ð¾Ð²Ñе ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ . Ð ÑÑом Ñазделе опиÑÑваеÑÑÑ, как опÑеделиÑÑ Ð½Ð¾Ð²Ñе базовÑе ÑипÑ, Ñо еÑÑÑ ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ , опиÑаннÑе ниже ÑÑÐ¾Ð²Ð½Ñ ÑзÑка SQL. ÐÐ»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ базового Ñипа Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑеализоваÑÑ ÑÑнкÑии, ÑабоÑаÑÑие Ñ ÑÑим Ñипом, на ÑзÑке низкого ÑÑовнÑ, обÑÑно C.
ÐÑимеÑÑ, ÑаÑÑмаÑÑиваемÑе в ÑÑой главе, можно найÑи в complex.sql и в complex.c в каÑалоге src/tutorial пакеÑа Ñ Ð¸ÑÑ
однÑм кодом. ÐнÑÑÑÑкÑии по запÑÑÐºÑ ÑÑиÑ
пÑимеÑов можно найÑи в Ñайле README в Ñом же каÑалоге.
ÐолÑзоваÑелÑÑкий Ñип должен вÑегда имеÑÑ ÑÑнкÑии ввода и вÑвода. ÐÑи ÑÑнкÑии опÑеделÑÑÑ, как Ñип бÑÐ´ÐµÑ Ð²ÑглÑдеÑÑ Ð² ÑÑÑоковом виде (пÑи вводе и вÑводе Ð´Ð»Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ) и как ÑÑÐ¾Ñ Ñип ÑазмеÑаеÑÑÑ Ð² памÑÑи. ФÑнкÑÐ¸Ñ Ð²Ð²Ð¾Ð´Ð° пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð² каÑеÑÑве аÑгÑменÑа ÑÑÑÐ¾ÐºÑ Ñимволов, заканÑиваÑÑÑÑÑÑ Ð½ÑлÑм, и возвÑаÑÐ°ÐµÑ Ð²Ð½ÑÑÑеннее пÑедÑÑавление Ñипа (в памÑÑи). ФÑнкÑÐ¸Ñ Ð²Ñвода пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð² каÑеÑÑве аÑгÑменÑа внÑÑÑеннее пÑедÑÑавление Ñипа и возвÑаÑÐ°ÐµÑ ÑÑÑÐ¾ÐºÑ Ñимволов, заканÑиваÑÑÑÑÑÑ Ð½ÑлÑм. ÐÑли Ð¼Ñ Ñ Ð¾Ñим не пÑоÑÑо ÑÐ¾Ñ ÑаниÑÑ Ñип, но делаÑÑ Ñ Ð½Ð¸Ð¼ неÑÑо болÑÑее, Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑедоÑÑавиÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе ÑÑнкÑии, ÑеализÑÑÑие вÑе опеÑаÑии, коÑоÑÑе Ð¼Ñ Ñ Ð¾Ñели Ð±Ñ Ð¸Ð¼ÐµÑÑ Ð´Ð»Ñ ÑÑого Ñипа.
ÐÑедположим, ÑÑо нам нÑжен Ñип complex, пÑедÑÑавлÑÑÑий комплекÑнÑе ÑиÑла. ÐÑÑеÑÑвеннÑм обÑазом комплекÑное ÑиÑло можно пÑедÑÑавиÑÑ Ð² памÑÑи в виде ÑледÑÑÑей ÑÑÑÑкÑÑÑÑ C:
typedef struct Complex {
double x;
double y;
} Complex; Ðам нÑжно бÑÐ´ÐµÑ Ð¿ÐµÑедаваÑÑ ÑÑÐ¾Ñ Ñип по ÑÑÑлке, Ñак как он ÑлиÑком велик, ÑÑÐ¾Ð±Ñ ÑмеÑÑиÑÑÑÑ Ð² одном знаÑении Datum.
РкаÑеÑÑве внеÑнего ÑÑÑокового пÑедÑÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ñипа Ð¼Ñ Ð²ÑбеÑем ÑÑÑÐ¾ÐºÑ Ð²Ð¸Ð´Ð° (x,y).
ФÑнкÑии ввода и вÑвода обÑÑно неÑложно напиÑаÑÑ, оÑобенно ÑÑнкÑÐ¸Ñ Ð²Ñвода. Ðо опÑеделÑÑ Ð²Ð½ÐµÑнее ÑÑÑоковое пÑедÑÑавление Ñипа, помниÑе, ÑÑо в конÑе конÑов вам пÑидÑÑÑÑ ÑеализоваÑÑ Ð·Ð°ÐºÐ¾Ð½ÑеннÑй и надÑжнÑй меÑод ÑазбоÑа ÑÑого пÑедÑÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² ÑÑнкÑии ввода. ÐапÑимеÑ, Ñак:
PG_FUNCTION_INFO_V1(complex_in);
Datum
complex_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
double x,
y;
Complex *result;
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for complex: \"%s\"",
str)));
result = (Complex *) palloc(sizeof(Complex));
result->x = x;
result->y = y;
PG_RETURN_POINTER(result);
}
ФÑнкÑÐ¸Ñ Ð²Ñвода Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿ÑоÑÑой:
PG_FUNCTION_INFO_V1(complex_out);
Datum
complex_out(PG_FUNCTION_ARGS)
{
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
char *result;
result = psprintf("(%g,%g)", complex->x, complex->y);
PG_RETURN_CSTRING(result);
}
Ðам нÑжно позабоÑиÑÑÑÑ Ð¾ Ñом, ÑÑÐ¾Ð±Ñ ÑÑнкÑии ввода и вÑвода бÑли обÑаÑнÑми дÑÑг к дÑÑгÑ. РпÑоÑивном ÑлÑÑае Ð²Ñ ÑÑолкнÑÑеÑÑ Ñ Ð¿Ñоблемами, когда вам поÑÑебÑеÑÑÑ Ð²ÑгÑÑзиÑÑ Ð´Ð°Ð½Ð½Ñе в Ñайл, а заÑем пÑоÑиÑаÑÑ Ð¸Ñ . ÐÑо оÑобенно ÑаÑпÑоÑÑÑанÑÐ½Ð½Ð°Ñ Ð¿Ñоблема, когда дело каÑаеÑÑÑ ÑиÑел Ñ Ð¿Ð»Ð°Ð²Ð°ÑÑей ÑоÑкой.
ÐополниÑелÑно полÑзоваÑелÑÑкий Ñип Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑедоÑÑавлÑÑÑ ÑÑнкÑии Ð´Ð»Ñ Ð²Ð²Ð¾Ð´Ð° и вÑвода в двоиÑном виде. ÐвоиÑнÑй ввод/вÑвод обÑÑно ÑабоÑÐ°ÐµÑ Ð±ÑÑÑÑее, но Ñ
Ñже поÑÑиÑÑеÑÑÑ, Ñем ÑекÑÑовÑй. Ðак и Ñ ÑекÑÑовÑм пÑедÑÑавлением, вÑбоÑ, каким бÑÐ´ÐµÑ Ð´Ð²Ð¾Ð¸Ñное пÑедÑÑавление, оÑÑаÑÑÑÑ Ð·Ð° вами. Ðногие вÑÑÑоеннÑе ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
ÑÑаÑаÑÑÑÑ Ð¾Ð±ÐµÑпеÑиÑÑ Ð´Ð²Ð¾Ð¸Ñное пÑедÑÑавление, незавиÑимое Ð¾Ñ Ð¼Ð°Ñинной аÑÑ
иÑекÑÑÑÑ. ÐÐ»Ñ Ñипа complex Ð¼Ñ Ð²Ð¾ÑполÑзÑемÑÑ ÑÑнкÑиÑми двоиÑного ввода/вÑвода Ñипа float8:
PG_FUNCTION_INFO_V1(complex_recv);
Datum
complex_recv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
Complex *result;
result = (Complex *) palloc(sizeof(Complex));
result->x = pq_getmsgfloat8(buf);
result->y = pq_getmsgfloat8(buf);
PG_RETURN_POINTER(result);
}
PG_FUNCTION_INFO_V1(complex_send);
Datum
complex_send(PG_FUNCTION_ARGS)
{
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
StringInfoData buf;
pq_begintypsend(&buf);
pq_sendfloat8(&buf, complex->x);
pq_sendfloat8(&buf, complex->y);
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
ÐапиÑав ÑÑнкÑии ввода/вÑвода и ÑкомпилиÑовав иÑ
в ÑазделÑемÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾ÑекÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ опÑеделиÑÑ Ñип complex в SQL. СнаÑала Ð¼Ñ Ð¾Ð±ÑÑвим его как Ñип-пÑÑÑÑÑкÑ:
CREATE TYPE complex;
ÐÑо Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ Ð½Ð°Ð¼ ÑÑÑлаÑÑÑÑ Ð½Ð° ÑÑÐ¾Ñ Ñип, опÑеделÑÑ Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ ÑÑнкÑии ввода/вÑвода. ТепеÑÑ Ð¼Ñ Ð¾Ð¿Ñеделим ÑÑнкÑии ввода/вÑвода:
CREATE FUNCTION complex_in(cstring)
RETURNS complex
AS 'имÑ_Ñайла'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION complex_out(complex)
RETURNS cstring
AS 'имÑ_Ñайла'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION complex_recv(internal)
RETURNS complex
AS 'имÑ_Ñайла'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION complex_send(complex)
RETURNS bytea
AS 'имÑ_Ñайла'
LANGUAGE C IMMUTABLE STRICT;ÐаконеÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пÑедоÑÑавиÑÑ Ð¿Ð¾Ð»Ð½Ð¾Ðµ опÑеделение Ñипа даннÑÑ :
CREATE TYPE complex ( internallength = 16, input = complex_in, output = complex_out, receive = complex_recv, send = complex_send, alignment = double );
Ðогда опÑеделÑеÑÑÑ Ð½Ð¾Ð²Ñй базовÑй Ñип, PostgreSQL авÑомаÑиÑеÑки обеÑпеÑÐ¸Ð²Ð°ÐµÑ Ð¿Ð¾Ð´Ð´ÐµÑÐ¶ÐºÑ Ð¼Ð°ÑÑивов Ñ ÑлеменÑами Ñакого Ñипа. Тип маÑÑива обÑÑно полÑÑÐ°ÐµÑ Ð¸Ð¼Ñ Ð¿Ð¾ имени базового Ñипа Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð½Ñм ÑпеÑеди Ñимволом подÑÑÑÐºÐ¸Ð²Ð°Ð½Ð¸Ñ (_).
Ðогда Ñип даннÑÑ Ð¾Ð¿ÑеделÑн, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ обÑÑвиÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе ÑÑнкÑии Ð´Ð»Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½ÑÑ Ð¾Ð¿ÐµÑаÑий Ñ ÑÑим Ñипом. ÐаÑем повеÑÑ ÑÑÐ¸Ñ ÑÑнкÑий могÑÑ Ð±ÑÑÑ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ñ Ð¾Ð¿ÐµÑаÑоÑÑ, а еÑли поÑÑебÑеÑÑÑ, и клаÑÑÑ Ð¾Ð¿ÐµÑаÑоÑов, Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑжки индекÑаÑии ÑÑого Ñипа. ÐÑи дополниÑелÑнÑе ÑÑовни обÑÑждаÑÑÑÑ Ð² ÑледÑÑÑÐ¸Ñ ÑÐ°Ð·Ð´ÐµÐ»Ð°Ñ .
ÐÑли внÑÑÑеннее пÑедÑÑавление Ñипа даннÑÑ
Ð¸Ð¼ÐµÐµÑ Ð¿ÐµÑеменнÑÑ Ð´Ð»Ð¸Ð½Ñ, оно должно ÑооÑвеÑÑÑвоваÑÑ ÑÑандаÑÑной ÑÑ
еме даннÑÑ
пеÑеменной длинÑ: пеÑвÑе ÑеÑÑÑе байÑа должно занимаÑÑ Ð¿Ð¾Ð»Ðµ char[4], к коÑоÑÐ¾Ð¼Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не ÑледÑÐµÑ Ð¾Ð±ÑаÑаÑÑÑÑ Ð½Ð°Ð¿ÑÑмÑÑ (по обÑÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð½Ð¾Ðµ vl_len_). ЧÑÐ¾Ð±Ñ ÑоÑ
ÑаниÑÑ Ð² ÑÑом поле ÑÐ°Ð·Ð¼ÐµÑ ÑлеменÑа (вклÑÑÐ°Ñ Ð´Ð»Ð¸Ð½Ñ Ñамого полÑ), Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¸ÑполÑзоваÑÑ Ð¼Ð°ÐºÑÐ¾Ñ SET_VARSIZE(), а ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ ÐµÐ³Ð¾ â макÑÐ¾Ñ VARSIZE(). (ÐÑи макÑоÑÑ Ð½ÑжнÑ, поÑÐ¾Ð¼Ñ ÑÑо поле Ð´Ð»Ð¸Ð½Ñ Ð¼Ð¾Ð¶ÐµÑ ÐºÐ¾Ð´Ð¸ÑоваÑÑÑÑ Ð¿Ð¾-ÑÐ°Ð·Ð½Ð¾Ð¼Ñ Ð½Ð° ÑазнÑÑ
плаÑÑоÑмаÑ
.)
Ðа дополниÑелÑнÑми подÑобноÑÑÑми обÑаÑиÑеÑÑ Ðº команде CREATE TYPE.
38.12.1. ÐÑобенноÑÑи TOAST
ÐÑли знаÑÐµÐ½Ð¸Ñ Ð²Ð°Ñего Ñипа даннÑÑ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ Ñазного ÑазмеÑа (во внÑÑÑенней ÑоÑме), обÑÑно Ð´Ð»Ñ Ñакого Ñипа желаÑелÑно ÑеализоваÑÑ Ð¿Ð¾Ð´Ð´ÐµÑÐ¶ÐºÑ TOAST (Ñм. Раздел 69.2). ÐÑо ÑледÑÐµÑ Ð´ÐµÐ»Ð°ÑÑ, даже еÑли знаÑÐµÐ½Ð¸Ñ ÑлиÑком Ð¼Ð°Ð»Ñ Ð´Ð»Ñ ÑжаÑÐ¸Ñ Ð¸Ð»Ð¸ внеÑнего Ñ ÑанениÑ, Ñак как TOAST позволÑÐµÑ ÑÑкономиÑÑ Ð¿ÑоÑÑÑанÑÑво и Ñ Ð´Ð°Ð½Ð½Ñми маленÑкого ÑазмеÑа, ÑокÑаÑÐ°Ñ Ð¸Ð·Ð´ÐµÑжки в заголовке.
ÐÐ»Ñ Ð¿Ð¾Ð´Ð´ÐµÑжки Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ TOAST ÑÑнкÑии на C, ÑабоÑаÑÑие Ñ Ñаким Ñипом даннÑÑ
, Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð·Ð°Ð±Ð¾ÑиÑÑÑÑ Ð¾ ÑаÑпаковке поÑÑÑпивÑиÑ
им даннÑÑ
, иÑполÑзÑÑ Ð¼Ð°ÐºÑÐ¾Ñ PG_DETOAST_DATUM. (ÐÑÑ Ð²Ð½ÑÑÑеннÑÑ Ð¾ÑобенноÑÑÑ Ð¾Ð±ÑÑно ÑкÑÑÐ²Ð°ÐµÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑй, опÑеделÑемÑй Ð´Ð»Ñ Ñипа макÑÐ¾Ñ GETARG_DATATYPE_P.) ÐаÑем, вÑполнÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ CREATE TYPE, ÑкажиÑе в каÑеÑÑве внÑÑÑенней Ð´Ð»Ð¸Ð½Ñ variable и вÑбеÑиÑе подÑ
одÑÑий ваÑÐ¸Ð°Ð½Ñ Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ (не plain).
ÐÑли вÑÑавнивание даннÑÑ
не Ð¸Ð¼ÐµÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ (либо ÑолÑко Ð´Ð»Ñ Ð½ÐµÐºÐ¾ÑоÑой ÑÑнкÑии, либо поÑÐ¾Ð¼Ñ ÑÑо Ð´Ð»Ñ Ñипа даннÑÑ
в лÑбом ÑлÑÑае пÑименÑеÑÑÑ Ð²ÑÑавнивание по байÑам), некоÑоÑÑÑ
издеÑжек, ÑвÑзаннÑÑ
Ñ Ð¼Ð°ÐºÑоÑом PG_DETOAST_DATUM, можно избежаÑÑ. ÐмеÑÑо него можно иÑполÑзоваÑÑ PG_DETOAST_DATUM_PACKED (его обÑÑно ÑкÑÑÐ²Ð°ÐµÑ Ð¾Ð¿ÑеделÑемÑй Ð´Ð»Ñ Ñипа макÑÐ¾Ñ GETARG_DATATYPE_PP) и воÑполÑзоваÑÑÑÑ Ð¼Ð°ÐºÑоÑами VARSIZE_ANY_EXHDR и VARDATA_ANY Ð´Ð»Ñ Ð¾Ð±ÑаÑÐµÐ½Ð¸Ñ Ðº поÑенÑиалÑно ÑжаÑÑм даннÑм. СÑÐ¾Ð¸Ñ ÐµÑÑ Ñаз оÑмеÑиÑÑ, ÑÑо даннÑе, возвÑаÑаемÑе ÑÑими макÑоÑами, не вÑÑавниваÑÑÑÑ, даже еÑли вÑÑавнивание задано в опÑеделении Ñипа. ÐÑли вÑÑавнивание важно, Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð·Ð°Ð´ÐµÐ¹ÑÑвоваÑÑ Ð¾Ð±ÑÑнÑй инÑеÑÑÐµÐ¹Ñ PG_DETOAST_DATUM.
ÐÑимеÑание
Ð ÑÑаÑом коде поле vl_len_ ÑаÑÑо обÑÑвлÑлоÑÑ ÐºÐ°Ðº int32, а не char[4]. ÐÑо ниÑем не ÑÑеваÑо до Ñой поÑÑ, пока в опÑеделении ÑÑÑÑкÑÑÑÑ Ð¸Ð¼ÐµÑÑÑÑ Ð´ÑÑгие Ð¿Ð¾Ð»Ñ Ñ Ð²ÑÑавниванием как минимÑм int32. Ðо Ñ Ð¿Ð¾ÑенÑиалÑно невÑÑовненнÑми даннÑми Ñакое опÑеделение ÑÑÑÑкÑÑÑÑ Ð¾Ð¿Ð°Ñно; компилÑÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²Ð¾ÑпÑинÑÑÑ ÐµÐ³Ð¾ как пÑаво полагаÑÑ, ÑÑо даннÑе вÑÑовненÑ, ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑивеÑÑи к аваÑийнÑм ÑбоÑм в аÑÑ
иÑекÑÑÑаÑ
, ÑÑÑогиÑ
к вÑÑавниваниÑ.
ÐоддеÑжка TOAST даÑÑ Ñакже возможноÑÑÑ Ð¸Ð¼ÐµÑÑ ÑазвÑÑнÑÑое пÑедÑÑавление даннÑÑ Ð² памÑÑи, ÑабоÑаÑÑ Ñ ÐºÐ¾ÑоÑÑм бÑÐ´ÐµÑ Ñдобнее, Ñем Ñ ÑоÑмаÑом Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð½Ð° диÑке. ÐбÑÑнÑй или «плоÑкий» ÑоÑÐ¼Ð°Ñ Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ varlena в конÑе конÑов пÑедÑÑавлÑÐµÑ Ñобой пÑоÑÑо Ð½Ð°Ð±Ð¾Ñ Ð±Ð°Ð¹Ñ; он не Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ ÑказаÑели, Ñак как ÑÑи байÑÑ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ ÑкопиÑÐ¾Ð²Ð°Ð½Ñ Ð² дÑÑгие адÑеÑа. ÐÐ»Ñ ÑложнÑÑ Ñипов даннÑÑ ÑабоÑаÑÑ Ñ Ð¿Ð»Ð¾Ñким ÑоÑмаÑом даннÑÑ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð´Ð¾Ð²Ð¾Ð»Ñно доÑого, Ñак ÑÑо PostgreSQL даÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Â«ÑазвеÑнÑÑÑ» плоÑкий ÑоÑÐ¼Ð°Ñ Ð² пÑедÑÑавление, более Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑее Ð´Ð»Ñ Ð²ÑÑиÑлений, и заÑем пеÑедаваÑÑ ÑÑÑ ÑÑÑÑкÑÑÑÑ Ð² памÑÑи ÑÑнкÑиÑм, ÑабоÑаÑÑим Ñ ÑÑим Ñипом.
ÐÐ»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑазвÑÑнÑÑого Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ñип даннÑÑ
должен опÑеделÑÑÑ ÑазвÑÑнÑÑÑй ÑоÑÐ¼Ð°Ñ Ð¿Ð¾ пÑавилам, опиÑаннÑм в src/include/utils/expandeddatum.h, и пÑедоÑÑавлÑÑÑ ÑÑнкÑии Ð´Ð»Ñ Â«ÑазвоÑаÑиваниÑ» плоÑкого знаÑÐµÐ½Ð¸Ñ Ð² ÑÑÐ¾Ñ ÑоÑмаÑ, а Ñакже Ð´Ð»Ñ Â«Ð·Ð°Ð²Ð¾ÑаÑиваниÑ» ÑÑого ÑоÑмаÑа опÑÑÑ Ð² обÑÑное пÑедÑÑавление varlena. ÐаÑем надо добиÑÑÑÑ, ÑÑÐ¾Ð±Ñ Ð²Ñе ÑÑнкÑии на C могли пÑинимаÑÑ Ð»Ñбое пÑедÑÑавление, возможно вÑполнÑÑ Ð¿ÑеобÑазование одного в дÑÑгое непоÑÑедÑÑвенно пÑи полÑÑении. ÐÐ»Ñ ÑÑого не ÑÑебÑеÑÑÑ Ð¸ÑпÑавлÑÑÑ ÑÑÐ°Ð·Ñ Ð²Ñе ÑÑÑеÑÑвÑÑÑие ÑÑнкÑии Ð´Ð»Ñ ÑÑого Ñипа даннÑÑ
, Ñак как имеÑÑийÑÑ ÑÑандаÑÑнÑй макÑÐ¾Ñ PG_DETOAST_DATUM ÑпоÑобен пÑеобÑазовÑваÑÑ ÑазвÑÑнÑÑÑе вÑ
однÑе даннÑе в обÑÑнÑй плоÑкий ÑоÑмаÑ. Таким обÑазом, вÑе ÑÑÑеÑÑвÑÑÑие ÑÑнкÑии, ÑабоÑаÑÑие Ñ Ð¿Ð»Ð¾Ñким ÑоÑмаÑом varlena пÑÐ¾Ð´Ð¾Ð»Ð¶Ð°Ñ ÑабоÑаÑÑ, Ñ
оÑÑ Ð¸ не оÑÐµÐ½Ñ ÑÑÑекÑивно, Ñ ÑазвÑÑнÑÑÑми вÑ
однÑми даннÑми; иÑ
необÑзаÑелÑно пеÑеделÑваÑÑ, пока не поÑÑебÑеÑÑÑ Ð¾Ð¿ÑимизиÑоваÑÑ Ð¿ÑоизводиÑелÑноÑÑÑ.
ФÑнкÑии на C, ÑмеÑÑие ÑабоÑаÑÑ Ñ ÑазвÑÑнÑÑÑм пÑедÑÑавлением, обÑÑно делÑÑÑÑ Ð½Ð° две каÑегоÑии: Ñе, ÑÑо могÑÑ ÑабоÑаÑÑ Ñ ÑазвÑÑнÑÑÑм ÑоÑмаÑом, и Ñе, ÑÑо могÑÑ Ð¿ÑинимаÑÑ Ð¸ ÑазвÑÑнÑÑÑе, и плоÑкие даннÑе varlena. ÐеÑвÑе пÑоÑе напиÑаÑÑ, но они могÑÑ Ð±ÑÑÑ Ð¼ÐµÐ½ÐµÐµ ÑÑÑекÑивнÑми в Ñелом, Ñак как пÑеобÑазование плоÑкого знаÑÐµÐ½Ð¸Ñ Ð² ÑазвÑÑнÑÑÑÑ ÑоÑÐ¼Ñ Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑолÑко одной ÑÑнкÑией Ð¼Ð¾Ð¶ÐµÑ ÑÑоиÑÑ Ð±Ð¾Ð»ÑÑе, Ñем ÑÑкономиÑÑÑ Ð¿Ñи обÑабоÑке даннÑÑ
в ÑазвÑÑнÑÑом ÑоÑмаÑе. Ðогда нÑжно ÑабоÑаÑÑ ÑолÑко Ñ ÑазвÑÑнÑÑÑм ÑоÑмаÑом, пÑеобÑазование плоÑкиÑ
знаÑений в ÑазвÑÑнÑÑÑÑ ÑоÑÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ ÑкÑÑÑÑ Ð² макÑоÑе, извлекаÑÑем аÑгÑменÑÑ, ÑÑÐ¾Ð±Ñ ÑÑнкÑÐ¸Ñ Ð±Ñла не Ñложнее, Ñем ÑабоÑаÑÑÐ°Ñ Ñ ÑÑадиÑионнÑми вÑ
однÑми даннÑми varlena. ЧÑÐ¾Ð±Ñ Ð¿ÑинимаÑÑ Ð¾Ð±Ð° ваÑианÑа вÑ
однÑÑ
знаÑений, напиÑиÑе ÑÑнкÑÐ¸Ñ Ð¸Ð·Ð²Ð»ÐµÑÐµÐ½Ð¸Ñ Ð°ÑгÑменÑов, коÑоÑÐ°Ñ Ð±ÑÐ´ÐµÑ ÑаÑпаковÑваÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ñ ÑокÑаÑÑннÑм заголовком, а Ñакже внеÑние и ÑжаÑÑе, но не ÑазвÑÑнÑÑÑе даннÑе. ТакÑÑ ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ опÑеделиÑÑ ÐºÐ°Ðº возвÑаÑаÑÑÑÑ ÑказаÑÐµÐ»Ñ Ð½Ð° обÑединение плоÑкого ÑоÑмаÑа varlena и ÑазвÑÑнÑÑого ÑоÑмаÑа. Ðакой ÑоÑÐ¼Ð°Ñ Ð¿Ð¾Ð»ÑÑен ÑакÑиÑеÑки, вÑзÑваÑÑий код Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð¿ÑеделиÑÑ, вÑзвав макÑÐ¾Ñ VARATT_IS_EXPANDED_HEADER().
ÐнÑÑаÑÑÑÑкÑÑÑа TOAST позволÑÐµÑ Ð½Ðµ ÑолÑко оÑлиÑиÑÑ Ð¾Ð±ÑÑнÑе знаÑÐµÐ½Ð¸Ñ varlena Ð¾Ñ ÑазвÑÑнÑÑÑÑ Ð·Ð½Ð°Ñений, но и ÑазлиÑиÑÑ ÑказаÑели Â«Ð´Ð»Ñ ÑÑениÑ/запиÑи» и «ÑолÑко Ð´Ð»Ñ ÑÑениÑ» на ÑазвÑÑнÑÑÑе знаÑениÑ. ФÑнкÑии на C, коÑоÑÑм нÑжно ÑиÑаÑÑ ÑазвÑÑнÑÑое знаÑение, или коÑоÑÑе бÑдÑÑ Ð¼ÐµÐ½ÑÑÑ ÐµÐ³Ð¾ безопаÑнÑм и невидимÑм извне обÑазом, могÑÑ Ð½Ðµ обÑаÑаÑÑ Ð²Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ Ð½Ð° Ñип полÑÑенного ÑказаÑелÑ. ÐÑли же ÑÑнкÑии на C вÑдаÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑннÑÑ Ð²ÐµÑÑÐ¸Ñ Ð²Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ знаÑениÑ, они могÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑÑÑ ÑазвÑÑнÑÑÑе Ð²Ñ Ð¾Ð´Ð½Ñе даннÑе на меÑÑе, ÑолÑко когда полÑÑаÑÑ ÑказаÑÐµÐ»Ñ Ð´Ð»Ñ ÑÑениÑ/запиÑи, но не когда полÑÑен ÑказаÑÐµÐ»Ñ ÑолÑко Ð´Ð»Ñ ÑÑениÑ. РпоÑледнем ÑлÑÑае они Ð´Ð¾Ð»Ð¶Ð½Ñ ÑнаÑала ÑкопиÑоваÑÑ Ð·Ð½Ð°Ñение и полÑÑиÑÑ Ð½Ð¾Ð²Ð¾Ðµ знаÑение, допÑÑкаÑÑее изменение. ФÑнкÑÐ¸Ñ Ð½Ð° C, ÑоздаÑÑÐ°Ñ Ð½Ð¾Ð²Ð¾Ðµ ÑазвÑÑнÑÑое знаÑение, должна вÑегда возвÑаÑаÑÑ ÑказаÑÐµÐ»Ñ Ð½Ð° него Ð´Ð»Ñ ÑÑениÑ/запиÑи. ÐÑоме Ñого, ÑÑнкÑиÑ, изменÑÑÑÐ°Ñ ÑазвÑÑнÑÑое знаÑение непоÑÑедÑÑвенно по ÑказаÑÐµÐ»Ñ Ð´Ð»Ñ ÑÑениÑ/запиÑи должна позабоÑиÑÑÑÑ Ð¾ Ñом, ÑÑÐ¾Ð±Ñ ÑÑо знаÑение оÑÑалоÑÑ Ð² пÑиемлемом ÑоÑÑоÑнии, еÑли она оÑÑабоÑÐ°ÐµÑ Ð½Ðµ полноÑÑÑÑ.
ÐÑимеÑÑ ÑабоÑÑ Ñ ÑазвÑÑнÑÑÑми знаÑениÑми можно найÑи в ÑÑандаÑÑной инÑÑаÑÑÑÑкÑÑÑе маÑÑивов, в ÑаÑÑноÑÑи в src/backend/utils/adt/array_expanded.c.