32.4. ÐÑполÑзование пеÑеменнÑÑ ÑÑедÑ
РРазделе 32.3 Ð²Ñ Ñвидели, как можно вÑполнÑÑÑ SQL-опеÑаÑоÑÑ Ð² пÑогÑамме Ñо вÑÑÑаиваемÑм SQL. ÐекоÑоÑÑе из ÑÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑоÑов иÑполÑзовали ÑолÑко ÑикÑиÑованнÑе знаÑÐµÐ½Ð¸Ñ Ð¸ не давали возможноÑÑи вÑÑавлÑÑÑ Ð² опеÑаÑоÑÑ Ð¿ÑоизволÑнÑе знаÑÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ обÑабаÑÑваÑÑ Ð·Ð½Ð°ÑениÑ, возвÑаÑÑннÑе запÑоÑом. ÐпеÑаÑоÑÑ Ñакого вида не оÑÐµÐ½Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ñ Ð² ÑеалÑнÑÑ Ð¿ÑиложениÑÑ . Ð ÑÑом Ñазделе подÑобно опиÑÑваеÑÑÑ, как можно пеÑедаваÑÑ Ð´Ð°Ð½Ð½Ñе Ð¼ÐµÐ¶Ð´Ñ Ð¿ÑогÑаммой на C и вÑÑÑаиваемÑми опеÑаÑоÑами SQL, иÑполÑзÑÑ Ð¿ÑоÑÑой Ð¼ÐµÑ Ð°Ð½Ð¸Ð·Ð¼, Ñак назÑваемÑе пеÑеменнÑе ÑÑедÑ. РпÑогÑамме Ñо вÑÑÑаиваемÑм SQL Ð¼Ñ ÑÑиÑаем SQL-опеÑаÑоÑÑ Ð²Ð½ÐµÐ´ÑÑннÑми в код пÑогÑÐ°Ð¼Ð¼Ñ Ð½Ð° C, ÑзÑке ÑÑедÑ. Таким обÑазом, пеÑеменнÑе пÑогÑÐ°Ð¼Ð¼Ñ Ð½Ð° C назÑваÑÑÑÑ Ð¿ÐµÑеменнÑми ÑÑедÑ.
ÐÑÑ Ð¾Ð´Ð¸Ð½ ÑпоÑоб пеÑедаÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¼ÐµÐ¶Ð´Ñ ÑеÑвеÑом Postgres Pro и пÑиложениÑми ECPG заклÑÑаеÑÑÑ Ð² иÑполÑзовании деÑкÑипÑоÑов SQL, как опиÑано в Разделе 32.7.
32.4.1. ÐбзоÑ
ÐеÑедаваÑÑ Ð´Ð°Ð½Ð½Ñе Ð¼ÐµÐ¶Ð´Ñ Ð¿ÑогÑаммой C и SQL-опеÑаÑоÑами во вÑÑÑаиваемом SQL оÑÐµÐ½Ñ Ð¿ÑоÑÑо. ÐмеÑÑо Ñого, ÑÑÐ¾Ð±Ñ Ð²ÑÑавлÑÑÑ Ð´Ð°Ð½Ð½Ñе в опеÑаÑоÑ, ÑÑо влеÑÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе ÑÑложнениÑ, в ÑаÑÑноÑÑи нÑжно пÑавилÑно заклÑÑаÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð² кавÑÑки, можно пÑоÑÑо запиÑаÑÑ Ð¸Ð¼Ñ Ð¿ÐµÑеменной C в SQL-опеÑаÑоÑе, пÑедваÑив его двоеÑоÑием. ÐапÑимеÑ:
EXEC SQL INSERT INTO sometable VALUES (:v1, 'foo', :v2);
ÐÑÐ¾Ñ Ð¾Ð¿ÐµÑаÑÐ¾Ñ Ð¾Ð±ÑаÑаеÑÑÑ Ðº двÑм пеÑеменнÑм C Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ v1 и v2 и Ñакже иÑполÑзÑÐµÑ Ð¾Ð±ÑÑнÑÑ ÑÑÑоковÑÑ ÐºÐ¾Ð½ÑÑанÑÑ SQL, показÑÐ²Ð°Ñ Ñем ÑамÑм, ÑÑо можно Ñвободно ÑоÑеÑаÑÑ ÑазнÑе Ð²Ð¸Ð´Ñ Ð´Ð°Ð½Ð½ÑÑ
.
ÐÑÐ¾Ñ Ð¼ÐµÑод вклÑÑÐµÐ½Ð¸Ñ Ð¿ÐµÑеменнÑÑ C в SQL-опеÑаÑоÑÑ ÑабоÑÐ°ÐµÑ Ð²ÐµÐ·Ð´Ðµ, где SQL-опеÑаÑÐ¾Ñ Ð¿ÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð²ÑÑажение знаÑениÑ.
32.4.2. СекÑии обÑÑвлений
ЧÑÐ¾Ð±Ñ Ð¿ÐµÑедаÑÑ Ð´Ð°Ð½Ð½Ñе из пÑогÑÐ°Ð¼Ð¼Ñ Ð² Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ , напÑимеÑ, в виде паÑамеÑÑов запÑоÑа, либо полÑÑиÑÑ Ð´Ð°Ð½Ð½Ñе из Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ Ð² пÑогÑамме, пеÑеменнÑе C, коÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ ÑодеÑжаÑÑ ÑÑи даннÑе, нÑжно обÑÑвиÑÑ Ð² ÑпеÑиалÑно помеÑеннÑÑ ÑекÑиÑÑ , ÑÑÐ¾Ð±Ñ Ð¿ÑепÑоÑеÑÑÐ¾Ñ Ð²ÑÑÑаиваемого SQL знал о Ð½Ð¸Ñ .
СекÑÐ¸Ñ Ð½Ð°ÑинаеÑÑÑ Ñ:
EXEC SQL BEGIN DECLARE SECTION;
и заканÑиваеÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹:
EXEC SQL END DECLARE SECTION;
ÐÐµÐ¶Ð´Ñ ÑÑими ÑÑÑоками Ð´Ð¾Ð»Ð¶Ð½Ñ ÑаÑполагаÑÑÑÑ Ð¾Ð±ÑÑнÑе обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿ÐµÑеменнÑÑ C, напÑимеÑ:
int x = 4; char foo[16], bar[16];
Ðак здеÑÑ Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð¾, пеÑеменной можно пÑиÑвоиÑÑ Ð½Ð°ÑалÑное знаÑение. ÐблаÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи пеÑеменной опÑеделÑеÑÑÑ ÑаÑположением ÑекÑии, в коÑоÑой она обÑÑвлÑеÑÑÑ Ð² пÑогÑамме. ÐÑ Ñакже можеÑе обÑÑвиÑÑ Ð¿ÐµÑеменнÑÑ ÑледÑÑÑим обÑазом (пÑи ÑÑом неÑвно ÑоздаÑÑÑÑ ÑекÑÐ¸Ñ Ð¾Ð±ÑÑвлений):
EXEC SQL int i = 4;
ÐÑ Ð¼Ð¾Ð¶ÐµÑе вклÑÑаÑÑ Ð² пÑогÑÐ°Ð¼Ð¼Ñ ÑÑолÑко ÑекÑий обÑÑвлений, ÑколÑко Ð·Ð°Ñ Ð¾ÑиÑе.
ÐÑи обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð²ÑводÑÑÑÑ Ð² ÑезÑлÑÑиÑÑÑÑий Ñайл как обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑÑнÑÑ Ð¿ÐµÑеменнÑÑ C, Ñак ÑÑо ÑÑи пеÑеменнÑе не нÑжно обÑÑвлÑÑÑ Ñнова. ÐеÑеменнÑе, коÑоÑÑе не пÑедназнаÑÐµÐ½Ñ Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ñ SQL, можно обÑÑвиÑÑ ÐºÐ°Ðº обÑÑно вне ÑÑÐ¸Ñ ÑпеÑиалÑнÑÑ ÑекÑий.
ÐпÑеделение ÑÑÑÑкÑÑÑÑ Ð¸Ð»Ð¸ обÑÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñоже должно ÑазмеÑаÑÑÑÑ Ð² ÑекÑии DECLARE. РпÑоÑивном ÑлÑÑае пÑепÑоÑеÑÑÐ¾Ñ Ð½Ðµ ÑÐ¼Ð¾Ð¶ÐµÑ Ð²Ð¾ÑпÑинÑÑÑ ÑÑи ÑипÑ, Ñак как не бÑÐ´ÐµÑ Ð·Ð½Ð°ÑÑ Ð¸Ñ
опÑеделениÑ.
32.4.3. ÐолÑÑение ÑезÑлÑÑаÑов запÑоÑа
ТепеÑÑ Ð²Ñ ÑмееÑе пеÑедаваÑÑ Ð´Ð°Ð½Ð½Ñе, подгоÑовленнÑе ваÑей пÑогÑаммой, в ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL. Ðо как полÑÑиÑÑ ÑезÑлÑÑаÑÑ Ð·Ð°Ð¿ÑоÑа? ÐÐ»Ñ ÑÑой Ñели во вÑÑÑаиваемом SQL еÑÑÑ Ð¾ÑобÑе ваÑиаÑии обÑÑнÑÑ
команд SELECT и FETCH. У ÑÑиÑ
команд еÑÑÑ ÑпеÑиалÑное пÑедложение INTO, опÑеделÑÑÑее, в какие пеÑеменнÑе ÑÑÐµÐ´Ñ Ð±ÑдÑÑ Ð¿Ð¾Ð¼ÐµÑÐµÐ½Ñ Ð¿Ð¾Ð»ÑÑаемÑе знаÑениÑ. SELECT иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑов, возвÑаÑаÑÑиÑ
ÑолÑко Ð¾Ð´Ð½Ñ ÑÑÑокÑ, а FETCH пÑименÑеÑÑÑ Ñ ÐºÑÑÑоÑом Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑов, возвÑаÑаÑÑиÑ
неÑколÑко ÑÑÑок.
ÐÑимеÑ:
/* * пÑедполагаеÑÑÑ ÑÑÑеÑÑвование Ñакой ÑаблиÑÑ: * CREATE TABLE test1 (a int, b varchar(50)); */ EXEC SQL BEGIN DECLARE SECTION; int v1; VARCHAR v2; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT a, b INTO :v1, :v2 FROM test;
ÐÑедложение INTO ÑазмеÑаеÑÑÑ Ð¼ÐµÐ¶Ð´Ñ ÑпиÑком вÑбоÑки и пÑедложением FROM. ЧиÑло ÑлеменÑов в ÑпиÑке вÑбоÑки должно ÑавнÑÑÑÑÑ ÑиÑÐ»Ñ ÑлеменÑов в ÑпиÑке поÑле INTO (Ñакже назÑваемом ÑелевÑм ÑпиÑком).
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑиÑÑÐµÑ Ð¸ÑполÑзование ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ FETCH:
EXEC SQL BEGIN DECLARE SECTION;
int v1;
VARCHAR v2;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL DECLARE foo CURSOR FOR SELECT a, b FROM test;
...
do
{
...
EXEC SQL FETCH NEXT FROM foo INTO :v1, :v2;
...
} while (...); ÐдеÑÑ Ð¿Ñедложение INTO ÑазмеÑаеÑÑÑ Ð¿Ð¾Ñле вÑеÑ
оÑÑалÑнÑÑ
обÑÑнÑÑ
пÑедложений.
32.4.4. СопоÑÑавление Ñипов
Ðогда пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ECPG пеÑедаÑÑ Ð´Ð°Ð½Ð½Ñе Ð¼ÐµÐ¶Ð´Ñ ÑеÑвеÑом Postgres Pro и пÑогÑаммой на C, напÑимеÑ, полÑÑÐ°Ñ ÑезÑлÑÑаÑÑ Ð·Ð°Ð¿ÑоÑа Ñ ÑеÑвеÑа или вÑполнÑÑ Ð¾Ð¿ÐµÑаÑоÑÑ SQL Ñ Ð²Ñ Ð¾Ð´Ð½Ñми паÑамеÑÑам, ÑÑи даннÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑеобÑазовÑваÑÑÑÑ Ð¸Ð· Ñипов Postgres Pro в ÑÐ¸Ð¿Ñ Ð¿ÐµÑеменнÑÑ ÑзÑка ÑÑÐµÐ´Ñ (а именно ÑÐ¸Ð¿Ñ ÑзÑка C) и наобоÑоÑ. Ðдно из главнÑÑ ÐºÐ°ÑеÑÑв ECPG ÑоÑÑÐ¾Ð¸Ñ Ð² Ñом, ÑÑо в болÑÑинÑÑве ÑлÑÑаев он Ð´ÐµÐ»Ð°ÐµÑ ÑÑо авÑомаÑиÑеÑки.
Ð ÑÑом оÑноÑении можно вÑделиÑÑ Ð´Ð²Ð° вида Ñипов даннÑÑ
. РпеÑÐ²Ð¾Ð¼Ñ Ð¾ÑноÑÑÑÑÑ Ð¿ÑоÑÑÑе ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
Postgres Pro, Ñакие как integer и text, коÑоÑÑе пÑиложение Ð¼Ð¾Ð¶ÐµÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно ÑиÑаÑÑ Ð¸ пиÑаÑÑ. С дÑÑгими Ñипами даннÑÑ
, Ñакими как timestamp и numeric, можно ÑабоÑаÑÑ ÑолÑко ÑеÑез ÑпеÑиалÑнÑе ÑÑнкÑии; Ñм. ÐодÑаздел 32.4.4.2.
РТаблиÑе 32.1 показано, как ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ Postgres Pro ÑооÑвеÑÑÑвÑÑÑ Ñипам даннÑÑ C. Ðогда нÑжно пеÑедаÑÑ Ð¸Ð»Ð¸ полÑÑиÑÑ Ð·Ð½Ð°Ñение опÑеделÑнного Ñипа даннÑÑ Postgres Pro, Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾Ð±ÑÑвиÑÑ Ð¿ÐµÑеменнÑÑ C ÑооÑвеÑÑÑвÑÑÑего Ñипа C в ÑекÑии обÑÑвлений.
ТаблиÑа 32.1. СооÑвеÑÑÑвие Ð¼ÐµÐ¶Ð´Ñ Ñипами даннÑÑ Postgres Pro и Ñипами пеÑеменнÑÑ C
| Тип даннÑÑ Postgres Pro | Тип пеÑеменной ÑÑÐµÐ´Ñ Ð¡ |
|---|---|
smallint | short |
integer | int |
bigint | long long int |
decimal | decimal[a] |
numeric | numeric[a] |
real | float |
double precision | double |
smallserial | short |
serial | int |
bigserial | long long int |
oid | unsigned int |
character(, varchar(, text | char[, VARCHAR[[b] |
name | char[NAMEDATALEN] |
timestamp | timestamp[a] |
interval | interval[a] |
date | date[a] |
boolean | bool[c] |
[a] С ÑÑим Ñипом можно ÑабоÑаÑÑ ÑолÑко ÑеÑез ÑпеÑиалÑнÑе ÑÑнкÑии; Ñм. ÐодÑаздел 32.4.4.2. [b] обÑÑвлÑеÑÑÑ Ð² [c] обÑÑвлÑеÑÑÑ Ð² | |
32.4.4.1. РабоÑа Ñ ÑимволÑнÑми ÑÑÑоками
ÐÐ»Ñ Ð¾Ð±ÑабоÑки Ñипов ÑимволÑнÑÑ
ÑÑÑок SQL, ÑакиÑ
как varchar и text, пÑедлагаÑÑÑÑ Ð´Ð²Ð° ваÑианÑа обÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿ÐµÑеменнÑÑ
ÑÑедÑ.
ÐеÑвÑй ÑпоÑоб заклÑÑаеÑÑÑ Ð² иÑполÑзовании char[], маÑÑива char, как ÑаÑе вÑего и пÑедÑÑавлÑÑÑÑÑ ÑимволÑнÑе даннÑе в C.
EXEC SQL BEGIN DECLARE SECTION;
char str[50];
EXEC SQL END DECLARE SECTION;ÐамеÑÑÑе, ÑÑо о длине ÑÑого маÑÑива Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð´ÑмаÑÑ Ñами. ÐÑли Ð²Ñ ÑкажеÑе даннÑÑ Ð¿ÐµÑеменнÑÑ ÑÑÐµÐ´Ñ Ð¡ в каÑеÑÑве Ñелевой пеÑеменной запÑоÑа, возвÑаÑаÑÑего ÑÑÑÐ¾ÐºÑ Ð´Ð»Ð¸Ð½Ð½ÐµÐµ 49 Ñимволов, пÑоизойдÑÑ Ð¿ÐµÑеполнение бÑÑеÑа.
РкаÑеÑÑве дÑÑгого подÑ
ода можно иÑполÑзоваÑÑ ÑпеÑиалÑнÑй Ñип VARCHAR, пÑедÑÑавленнÑй в ECPG. ÐпÑеделение маÑÑива Ñипа VARCHAR пÑеобÑазÑеÑÑÑ Ð² ÑÑÑÑкÑÑÑÑ (struct) Ñ ÑобÑÑвеннÑм именем Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ пеÑеменной. ÐбÑÑвление вида:
VARCHAR var[180];
пÑеобÑазÑеÑÑÑ Ð²:
struct varchar_var { int len; char arr[180]; } var; Член ÑÑÑÑкÑÑÑÑ arr ÑодеÑÐ¶Ð¸Ñ ÑÑÑокÑ, вклÑÑаÑÑÑÑ Ð·Ð°Ð²ÐµÑÑаÑÑий нÑлевой байÑ. Таким обÑазом, ÑÑÐ¾Ð±Ñ ÑоÑ
ÑаниÑÑ ÑÑÑÐ¾ÐºÑ Ð² пеÑеменной Ñипа VARCHAR, ÑÑа пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° бÑÑÑ Ð¾Ð±ÑÑвлена Ñ Ð´Ð»Ð¸Ð½Ð¾Ð¹, ÑÑиÑÑваÑÑей завеÑÑаÑÑий нÑлевой байÑ. Член ÑÑÑÑкÑÑÑÑ len ÑодеÑÐ¶Ð¸Ñ Ð´Ð»Ð¸Ð½Ñ ÑÑÑоки, ÑоÑ
ÑанÑнной в arr, без завеÑÑаÑÑего нÑлевого байÑа. Ðогда на вÑ
од запÑоÑÑ Ð¿Ð¾Ð´Ð°ÑÑÑÑ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ ÑÑÐµÐ´Ñ C, Ñ ÐºÐ¾ÑоÑой strlen(arr) оÑлиÑаеÑÑÑ Ð¾Ñ len, пÑименÑеÑÑÑ Ð½Ð°Ð¸Ð¼ÐµÐ½ÑÑее знаÑение.
VARCHAR можно запиÑаÑÑ Ð² веÑÑ
нем или нижнем ÑегиÑÑÑе, но не в ÑмеÑанном.
ÐеÑеменнÑе char и VARCHAR Ñакже могÑÑ ÑодеÑжаÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð´ÑÑгиÑ
Ñипов SQL в иÑ
ÑÑÑоковом пÑедÑÑавлении.
32.4.4.2. ÐбÑабоÑка ÑпеÑиалÑнÑÑ Ñипов даннÑÑ
ECPG пÑедÑÑавлÑÐµÑ Ð½ÐµÐºÐ¾ÑоÑÑе оÑобÑе ÑипÑ, коÑоÑÑе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð¼Ð¾ÑÑ Ð²Ð°Ð¼ легко опеÑиÑоваÑÑ Ð½ÐµÐºÐ¾ÑоÑÑми ÑпеÑиалÑнÑми Ñипами даннÑÑ
Postgres Pro. Ð ÑаÑÑноÑÑи, в нÑм Ñеализована поддеÑжка Ñипов numeric, decimal, date, timestamp и interval. ÐÐ»Ñ ÑÑиÑ
Ñипов нелÑÐ·Ñ Ð¿Ð¾Ð´Ð¾Ð±ÑаÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾Ðµ ÑооÑвеÑÑÑвие Ñ Ð¿ÑимиÑивнÑми Ñипами ÑÑÐµÐ´Ñ (напÑимеÑ, int, long long int или char[]), Ñак как они имеÑÑ ÑложнÑÑ Ð²Ð½ÑÑÑеннÑÑ ÑÑÑÑкÑÑÑÑ. ÐÑиложениÑ, ÑабоÑаÑÑие Ñ ÑÑими Ñипами, Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾Ð±ÑÑвлÑÑÑ Ð¿ÐµÑеменнÑе оÑобÑÑ
Ñипов и ÑабоÑаÑÑ Ñ Ð½Ð¸Ð¼Ð¸, пÑименÑÑ ÑÑнкÑии из библиоÑеки pgtypes. ÐÑа библиоÑека, подÑобно опиÑÐ°Ð½Ð½Ð°Ñ Ð² Разделе 32.6 ÑодеÑÐ¶Ð¸Ñ Ð±Ð°Ð·Ð¾Ð²Ñе ÑÑнкÑии Ð´Ð»Ñ Ð¾Ð¿ÐµÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑÑими Ñипами, ÑÑÐ¾Ð±Ñ Ð²Ð°Ð¼ не ÑÑебовалоÑÑ, напÑимеÑ, пеÑедаваÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ SQL-ÑеÑвеÑÑ, когда нÑжно пÑоÑÑо добавиÑÑ Ð¸Ð½ÑеÑвал к знаÑÐµÐ½Ð¸Ñ Ð²Ñемени.
ÐÑи оÑобÑе ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¾Ð¿Ð¸ÑÐ°Ð½Ñ Ð² ÑледÑÑÑÐ¸Ñ Ð¿Ð¾Ð´ÑÐ°Ð·Ð´ÐµÐ»Ð°Ñ . ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð´Ñобнее ÑзнаÑÑ Ð¾ ÑÑнкÑиÑÑ Ð² библиоÑеке pgtypes, обÑаÑиÑеÑÑ Ðº РазделÑ 32.6.
32.4.4.2.1. timestamp, date
ÐÐ»Ñ ÑабоÑÑ Ñ Ð¿ÐµÑеменнÑми timestamp в пÑиложении ECPG пÑименÑеÑÑÑ ÑледÑÑÑÐ°Ñ ÑÑ
ема.
СнаÑала в пÑогÑÐ°Ð¼Ð¼Ñ Ð½Ñжно вклÑÑиÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾ÑнÑй Ñайл, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¾Ð¿Ñеделение Ñипа timestamp:
#include <pgtypes_timestamp.h>
ÐаÑем обÑÑвиÑе в ÑекÑии обÑÑвлений пеÑеменнÑÑ Ñипа timestamp:
EXEC SQL BEGIN DECLARE SECTION; timestamp ts; EXEC SQL END DECLARE SECTION;
ÐÑоÑиÑав знаÑение в ÑÑÑ Ð¿ÐµÑеменнÑÑ, вÑполнÑйÑе дейÑÑÐ²Ð¸Ñ Ñ Ð½Ð¸Ð¼, иÑполÑзÑÑ ÑÑнкÑии в библиоÑеке pgtypes. Ð ÑледÑÑÑем пÑимеÑе знаÑение timestamp пÑеобÑазÑеÑÑÑ Ð² ÑекÑÑовÑй вид (ASCII) Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑнкÑии PGTYPEStimestamp_to_asc():
EXEC SQL SELECT now()::timestamp INTO :ts;
printf("ts = %s\n", PGTYPEStimestamp_to_asc(ts));ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð²ÑÐ²ÐµÐ´ÐµÑ Ñакой ÑезÑлÑÑаÑ:
ts = 2010-06-27 18:03:56.949343
Таким же обÑазом можно ÑабоÑаÑÑ Ð¸ Ñ Ñипом DATE. РпÑогÑÐ°Ð¼Ð¼Ñ Ð½Ñжно вклÑÑиÑÑ pgtypes_date.h, обÑÑвиÑÑ Ð¿ÐµÑеменнÑÑ Ñипа date, и заÑем можно бÑÐ´ÐµÑ Ð¿ÑеобÑазоваÑÑ Ð·Ð½Ð°Ñение DATE в ÑекÑÑовÑй вид, иÑполÑзÑÑ ÑÑнкÑÐ¸Ñ PGTYPESdate_to_asc(). ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð´Ñобнее ÑзнаÑÑ Ð¾ ÑÑнкÑиÑÑ
в библиоÑеке pgtypes, обÑаÑиÑеÑÑ Ðº РазделÑ 32.6.
32.4.4.2.2. interval
ÐÑинÑип ÑабоÑÑ Ñ Ñипом interval ÑÐ¾Ñ Ð¶Ðµ, ÑÑо и Ñ Ñипами timestamp и date, однако Ð´Ð»Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ñипа interval нÑжно Ñвно вÑделиÑÑ Ð¿Ð°Ð¼ÑÑÑ. ÐÑÑгими Ñловами, блок памÑÑи Ð´Ð»Ñ ÑÑой пеÑеменной должен ÑазмеÑаÑÑÑÑ Ð² облаÑÑи кÑÑи, а не в ÑÑеке.
ÐÑÐ¸Ð¼ÐµÑ Ð¿ÑогÑаммÑ:
#include <stdio.h>
#include <stdlib.h>
#include <pgtypes_interval.h>
int
main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
interval *in;
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO testdb;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
in = PGTYPESinterval_new();
EXEC SQL SELECT '1 min'::interval INTO :in;
printf("interval = %s\n", PGTYPESinterval_to_asc(in));
PGTYPESinterval_free(in);
EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;
return 0;
}32.4.4.2.3. numeric, decimal
Ð¢Ð¸Ð¿Ñ numeric и decimal обÑабаÑÑваÑÑÑÑ Ñак же, как и Ñип interval: Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾Ð¿ÑеделиÑÑ ÑказаÑелÑ, вÑделиÑÑ Ð½ÐµÐºÐ¾ÑоÑое пÑоÑÑÑанÑÑво памÑÑи в кÑÑе и обÑаÑаÑÑÑÑ Ðº пеÑеменной, иÑполÑзÑÑ ÑÑнкÑии в библиоÑеке pgtypes. ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð´Ñобнее ÑзнаÑÑ Ð¾ ÑÑнкÑиÑÑ
в библиоÑеке pgtypes, обÑаÑиÑеÑÑ Ðº РазделÑ 32.6.
ÐÐ»Ñ Ñипа decimal никакие ÑпеÑиалÑнÑе ÑÑнкÑии не ÑеализованÑ. ÐÐ»Ñ Ð´Ð°Ð»ÑнейÑей обÑабоÑки пÑиложение должно пÑеобÑазоваÑÑ ÐµÐ³Ð¾ в пеÑеменнÑÑ numeric, пÑименив ÑÑнкÑÐ¸Ñ Ð¸Ð· библиоÑеки pgtypes.
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑиÑÑÐµÑ ÑабоÑÑ Ñ Ð¿ÐµÑеменнÑми Ñипов numeric и decimal.
#include <stdio.h>
#include <stdlib.h>
#include <pgtypes_numeric.h>
EXEC SQL WHENEVER SQLERROR STOP;
int
main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
numeric *num;
numeric *num2;
decimal *dec;
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO testdb;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
num = PGTYPESnumeric_new();
dec = PGTYPESdecimal_new();
EXEC SQL SELECT 12.345::numeric(4,2), 23.456::decimal(4,2) INTO :num, :dec;
printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 0));
printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 1));
printf("numeric = %s\n", PGTYPESnumeric_to_asc(num, 2));
/* ÐÑеобÑазоваÑÑ decimal в numeric, ÑÑÐ¾Ð±Ñ Ð²ÑвеÑÑи деÑÑÑиÑное знаÑение. */
num2 = PGTYPESnumeric_new();
PGTYPESnumeric_from_decimal(dec, num2);
printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 0));
printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 1));
printf("decimal = %s\n", PGTYPESnumeric_to_asc(num2, 2));
PGTYPESnumeric_free(num2);
PGTYPESdecimal_free(dec);
PGTYPESnumeric_free(num);
EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;
return 0;
}32.4.4.3. ÐеÑеменнÑе ÑÑÐµÐ´Ñ Ð´Ð»Ñ Ð½ÐµÐ¿ÑимиÑивнÑÑ Ñипов
РкаÑеÑÑве пеÑеменнÑÑ ÑÑÐµÐ´Ñ Ñакже можно иÑполÑзоваÑÑ Ð¼Ð°ÑÑивÑ, опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñипов, ÑÑÑÑкÑÑÑÑ Ð¸ ÑказаÑели.
32.4.4.3.1. ÐаÑÑивÑ
ÐÐ»Ñ Ð¿ÑÐ¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð°ÑÑивов в каÑеÑÑве пеÑеменнÑÑ
ÑÑÐµÐ´Ñ ÐµÑÑÑ Ð´Ð²Ð° ваÑианÑа иÑполÑзованиÑ. Ðо-пеÑвÑÑ
, в маÑÑиве char[] или VARCHAR[] можно ÑоÑ
ÑаниÑÑ ÑекÑÑовÑÑ ÑÑÑокÑ, как ÑаÑÑказÑвалоÑÑ Ð² ÐодÑазделе 32.4.4.1. Ðо-вÑоÑÑÑ
, в маÑÑив можно полÑÑиÑÑ Ð½ÐµÑколÑко ÑÑÑок из ÑезÑлÑÑаÑа запÑоÑа, не иÑполÑзÑÑ ÐºÑÑÑоÑ. ЧÑÐ¾Ð±Ñ Ð½Ðµ пÑименÑÑ Ð¼Ð°ÑÑивÑ, обÑабоÑаÑÑ ÑезÑлÑÑÐ°Ñ Ð·Ð°Ð¿ÑоÑа, ÑоÑÑоÑÑий из неÑколÑкиÑ
ÑÑÑок, нÑжно иÑполÑзоваÑÑ ÐºÑÑÑÐ¾Ñ Ð¸ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ FETCH. Ðо Ñ Ð¿ÐµÑеменнÑми-маÑÑивами неÑколÑко ÑÑÑок можно полÑÑиÑÑ ÑÑазÑ. Ðлина опÑеделÑемого маÑÑива должна бÑÑÑ Ð´Ð¾ÑÑаÑоÑной Ð´Ð»Ñ ÑазмеÑÐµÐ½Ð¸Ñ Ð²ÑеÑ
ÑÑÑок, инаÑе ÑкоÑее вÑего пÑоизойдÑÑ Ð¿ÐµÑеполнение бÑÑеÑа.
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ ÑканиÑÑÐµÑ ÑиÑÑемнÑÑ ÑаблиÑÑ pg_database и показÑÐ²Ð°ÐµÑ Ð²Ñе OID и имена доÑÑÑпнÑÑ
баз даннÑÑ
:
int
main(void)
{
EXEC SQL BEGIN DECLARE SECTION;
int dbid[8];
char dbname[8][16];
int i;
EXEC SQL END DECLARE SECTION;
memset(dbname, 0, sizeof(char)* 16 * 8);
memset(dbid, 0, sizeof(int) * 8);
EXEC SQL CONNECT TO testdb;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
/* ÐолÑÑиÑÑ Ð² маÑÑÐ¸Ð²Ñ ÑÑÐ°Ð·Ñ Ð½ÐµÑколÑко ÑÑÑок. */
EXEC SQL SELECT oid,datname INTO :dbid, :dbname FROM pg_database;
for (i = 0; i < 8; i++)
printf("oid=%d, dbname=%s\n", dbid[i], dbname[i]);
EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;
return 0;
}ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð²ÑÐ²Ð¾Ð´Ð¸Ñ ÑледÑÑÑий ÑезÑлÑÑаÑ. (ТоÑнÑе знаÑÐµÐ½Ð¸Ñ Ð·Ð°Ð²Ð¸ÑÑÑ Ð¾Ñ Ð»Ð¾ÐºÐ°Ð»ÑнÑÑ Ð¾Ð±ÑÑоÑÑелÑÑÑв.)
oid=1, dbname=template1 oid=11510, dbname=template0 oid=11511, dbname=postgres oid=313780, dbname=testdb oid=0, dbname= oid=0, dbname= oid=0, dbname=
32.4.4.3.2. СÑÑÑкÑÑÑÑ
ÐÐ»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñений ÑÑÐ°Ð·Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑолбÑов можно пÑимениÑÑ ÑÑÑÑкÑÑÑÑ, имена Ñленов коÑоÑой ÑовпадаÑÑ Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ ÑÑолбÑов ÑезÑлÑÑаÑа запÑоÑа. СÑÑÑкÑÑÑа позволÑÐµÑ Ð¾Ð±ÑабаÑÑваÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑолбÑов в одной пеÑеменной ÑÑÐµÐ´Ñ Ð¡.
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ OID, имена и ÑазмеÑÑ Ð¸Ð¼ÐµÑÑиÑ
ÑÑ Ð±Ð°Ð· даннÑÑ
из ÑиÑÑемной ÑаблиÑÑ pg_database, иÑполÑзÑÑ Ð¿Ñи ÑÑом ÑÑнкÑÐ¸Ñ pg_database_size(). Ð ÑÑом пÑимеÑе пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñипа ÑÑÑÑкÑÑÑÑ dbinfo_t Ñ Ñленами, имена коÑоÑÑÑ
ÑооÑвеÑÑÑвÑÑÑ Ð¸Ð¼ÐµÐ½Ð°Ð¼ вÑеÑ
ÑÑолбÑов ÑезÑлÑÑаÑа SELECT, пÑименÑеÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð¹ ÑÑÑоки ÑезÑлÑÑаÑа без вовлеÑÐµÐ½Ð¸Ñ Ð² опеÑаÑÐ¾Ñ FETCH неÑколÑкиÑ
пеÑеменнÑÑ
ÑÑедÑ.
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int oid;
char datname[65];
long long int size;
} dbinfo_t;
dbinfo_t dbval;
EXEC SQL END DECLARE SECTION;
memset(&dbval, 0, sizeof(dbinfo_t));
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database;
EXEC SQL OPEN cur1;
/* по доÑÑижении конÑа набоÑа ÑезÑлÑÑаÑов пÑеÑваÑÑ Ñикл while */
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* ÐÑбÑаÑÑ Ð½ÐµÑколÑко ÑÑолбÑов в Ð¾Ð´Ð½Ñ ÑÑÑÑкÑÑÑÑ. */
EXEC SQL FETCH FROM cur1 INTO :dbval;
/* ÐапеÑаÑаÑÑ ÑÐ»ÐµÐ½Ñ ÑÑÑÑкÑÑÑÑ. */
printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, dbval.size);
}
EXEC SQL CLOSE cur1;ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑледÑÑÑий ÑезÑлÑÑаÑ. (ТоÑнÑе знаÑÐµÐ½Ð¸Ñ Ð·Ð°Ð²Ð¸ÑÑÑ Ð¾Ñ Ð»Ð¾ÐºÐ°Ð»ÑнÑÑ Ð¾Ð±ÑÑоÑÑелÑÑÑв.)
oid=1, datname=template1, size=4324580 oid=11510, datname=template0, size=4243460 oid=11511, datname=postgres, size=4324580 oid=313780, datname=testdb, size=8183012
ÐеÑеменнÑе ÑÑÐµÐ´Ñ Ñипа ÑÑÑÑкÑÑÑÑ Â«Ð²Ð±Ð¸ÑаÑÑ Ð² ÑебÑ» ÑÑолÑко ÑÑолбÑов, ÑколÑко полей ÑодеÑÐ¶Ð¸Ñ ÑÑÑÑкÑÑÑа. ÐнаÑÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑÑ
ÑÑолбÑов можно пÑиÑвоиÑÑ Ð´ÑÑгим пеÑеменнÑм ÑÑедÑ. ÐапÑимеÑ, пÑиведÑннÑÑ Ð²ÑÑе пÑогÑÐ°Ð¼Ð¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ видоизмениÑÑ ÑледÑÑÑим обÑазом, ÑазмеÑÑив пеÑеменнÑÑ size вне ÑÑÑÑкÑÑÑÑ:
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int oid;
char datname[65];
} dbinfo_t;
dbinfo_t dbval;
long long int size;
EXEC SQL END DECLARE SECTION;
memset(&dbval, 0, sizeof(dbinfo_t));
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size FROM pg_database;
EXEC SQL OPEN cur1;
/* по доÑÑижении конÑа набоÑа ÑезÑлÑÑаÑов пÑеÑваÑÑ Ñикл while */
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* ÐÑбÑаÑÑ Ð½ÐµÑколÑко ÑÑолбÑов в Ð¾Ð´Ð½Ñ ÑÑÑÑкÑÑÑÑ. */
EXEC SQL FETCH FROM cur1 INTO :dbval, :size;
/* ÐапеÑаÑаÑÑ ÑÐ»ÐµÐ½Ñ ÑÑÑÑкÑÑÑÑ. */
printf("oid=%d, datname=%s, size=%lld\n", dbval.oid, dbval.datname, size);
}
EXEC SQL CLOSE cur1;32.4.4.3.3. ÐпÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñипов
ЧÑÐ¾Ð±Ñ ÑопоÑÑавиÑÑ Ð½Ð¾Ð²Ñе ÑÐ¸Ð¿Ñ Ñ Ñже ÑÑÑеÑÑвÑÑÑими, иÑполÑзÑйÑе клÑÑевое Ñлово typedef.
EXEC SQL BEGIN DECLARE SECTION;
typedef char mychartype[40];
typedef long serial_t;
EXEC SQL END DECLARE SECTION;ÐамеÑÑÑе, ÑÑо Ð²Ñ Ñакже можеÑе напиÑаÑÑ:
EXEC SQL TYPE serial_t IS long;
ÐÑо обÑÑвление не обÑзаÑелÑно должно Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑÑ Ð² ÑекÑии обÑÑвлений.
32.4.4.3.4. УказаÑели
ÐÑ Ð¼Ð¾Ð¶ÐµÑе обÑÑвлÑÑÑ ÑказаÑели на ÑамÑе ÑаÑпÑоÑÑÑанÑннÑе ÑипÑ. УÑÑиÑе, однако, ÑÑо ÑказаÑели нелÑÐ·Ñ Ð¸ÑполÑзоваÑÑ Ð² каÑеÑÑве ÑелевÑÑ Ð¿ÐµÑеменнÑÑ Ð·Ð°Ð¿ÑоÑов без авÑовÑделениÑ. Ðа дополниÑелÑнÑми ÑведениÑми об авÑовÑделении обÑаÑиÑеÑÑ Ðº РазделÑ 32.7.
EXEC SQL BEGIN DECLARE SECTION;
int *intp;
char **charp;
EXEC SQL END DECLARE SECTION;32.4.5. ÐбÑабоÑка непÑимиÑивнÑÑ Ñипов даннÑÑ SQL
Ð ÑÑом Ñазделе опиÑÑваеÑÑÑ ÐºÐ°Ðº ÑабоÑаÑÑ Ñ Ð½ÐµÑкалÑÑнÑми и полÑзоваÑелÑÑкими Ñипами ÑÑÐ¾Ð²Ð½Ñ SQL в пÑиложениÑÑ ECPG. ÐамеÑÑÑе, ÑÑо ÑÑÐ¾Ñ Ð¿Ð¾Ð´Ñ Ð¾Ð´ оÑлиÑаеÑÑÑ Ð¾Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÐµÑеменнÑÑ Ð½ÐµÐ¿ÑимиÑивнÑÑ Ñипов, опиÑанного в пÑедÑдÑÑем Ñазделе.
32.4.5.1. ÐаÑÑивÑ
ÐногомеÑнÑе маÑÑÐ¸Ð²Ñ ÑÑÐ¾Ð²Ð½Ñ SQL в ECPG напÑÑмÑÑ Ð½Ðµ поддеÑживаÑÑÑÑ, но одномеÑнÑе маÑÑÐ¸Ð²Ñ ÑÑÐ¾Ð²Ð½Ñ SQL могÑÑ Ð±ÑÑÑ ÑопоÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ñ Ð¿ÐµÑеменнÑми-маÑÑивами ÑÑÐµÐ´Ñ C и наобоÑоÑ. Ðднако ÑÑÑиÑе, ÑÑо когда ÑоздаÑÑÑÑ Ð¾Ð¿ÐµÑаÑоÑ, ecpg не Ð·Ð½Ð°ÐµÑ Ñипов ÑÑолбÑов, поÑÑÐ¾Ð¼Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑовеÑиÑÑ, вводиÑÑÑ Ð»Ð¸ маÑÑив C в ÑооÑвеÑÑÑвÑÑÑий маÑÑив ÑÑÐ¾Ð²Ð½Ñ SQL. ÐбÑабаÑÑÐ²Ð°Ñ ÑезÑлÑÑÐ°Ñ SQL-опеÑаÑоÑа, ecpg Ð¸Ð¼ÐµÐµÑ Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼ÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¸ Ñаким обÑазом Ð¼Ð¾Ð¶ÐµÑ ÑбедиÑÑÑÑ, ÑÑо Ñ Ð¾Ð±ÐµÐ¸Ñ ÑÑоÑон маÑÑивÑ.
ÐÑли запÑÐ¾Ñ Ð¾Ð±ÑаÑаеÑÑÑ Ðº оÑделÑнÑм ÑлеменÑам маÑÑива, ÑÑо избавлÑÐµÑ Ð¾Ñ Ð½ÐµÐ¾Ð±Ñ
одимоÑÑи пÑименÑÑÑ Ð¼Ð°ÑÑÐ¸Ð²Ñ Ð² ECPG. Ð ÑÑом ÑлÑÑае ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð¿ÐµÑеменнÑÑ ÑÑÐµÐ´Ñ Ð¡, имеÑÑÑÑ Ñип, коÑоÑÑй можно ÑопоÑÑавиÑÑ ÑÐ¸Ð¿Ñ ÑлеменÑа. ÐапÑимеÑ, еÑли Ñипом ÑÑолбÑа ÑвлÑеÑÑÑ Ð¼Ð°ÑÑив integer, можно иÑполÑзоваÑÑ Ð¿ÐµÑеменнÑÑ ÑÑÐµÐ´Ñ Ñипа int. ÐналогиÑно, еÑли Ñип ÑлеменÑа â varchar или text, можно иÑполÑзоваÑÑ Ð¿ÐµÑеменнÑÑ Ñипа char[] или VARCHAR[].
ÐÑедположим, ÑÑо Ñ Ð½Ð°Ñ ÐµÑÑÑ ÑаблиÑа:
CREATE TABLE t3 (
ii integer[]
);
testdb=> SELECT * FROM t3;
ii
-------------
{1,2,3,4,5}
(1 row) СледÑÑÑÐ°Ñ Ð¿ÑогÑамма полÑÑÐ°ÐµÑ 4-Ñй ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¼Ð°ÑÑива и ÑоÑ
ÑанÑÐµÑ ÐµÐ³Ð¾ в пеÑеменной ÑÑÐµÐ´Ñ Ð¡, имеÑÑей Ñип int:
EXEC SQL BEGIN DECLARE SECTION;
int ii;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE cur1 CURSOR FOR SELECT ii[4] FROM t3;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
EXEC SQL FETCH FROM cur1 INTO :ii ;
printf("ii=%d\n", ii);
}
EXEC SQL CLOSE cur1;ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð²ÑÐ²Ð¾Ð´Ð¸Ñ ÑледÑÑÑий ÑезÑлÑÑаÑ:
ii=4
ЧÑÐ¾Ð±Ñ ÑопоÑÑавиÑÑ Ð½ÐµÑколÑко ÑлеменÑов маÑÑива Ñ Ð½ÐµÑколÑкими ÑлеменÑами пеÑеменной-маÑÑивом ÑÑедÑ, каждÑй ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¼Ð°ÑÑива SQL нÑжно по оÑделÑноÑÑи ÑвÑзаÑÑ Ñ ÐºÐ°Ð¶Ð´Ñм ÑлеменÑом маÑÑива ÑÑедÑ, напÑимеÑ:
EXEC SQL BEGIN DECLARE SECTION;
int ii_a[8];
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE cur1 CURSOR FOR SELECT ii[1], ii[2], ii[3], ii[4] FROM t3;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
EXEC SQL FETCH FROM cur1 INTO :ii_a[0], :ii_a[1], :ii_a[2], :ii_a[3];
...
}ÐÑÑ Ñаз обÑаÑиÑе внимание, ÑÑо в ÑÑом ÑлÑÑае ваÑианÑ
EXEC SQL BEGIN DECLARE SECTION;
int ii_a[8];
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE cur1 CURSOR FOR SELECT ii FROM t3;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* ÐÐÐÐ ÐÐÐÐЬÐÐ */
EXEC SQL FETCH FROM cur1 INTO :ii_a;
...
}не бÑÐ´ÐµÑ ÑабоÑаÑÑ ÐºÐ¾ÑÑекÑно, Ñак как ÑÑÐ¾Ð»Ð±ÐµÑ Ñ Ñипом маÑÑива нелÑÐ·Ñ Ð½Ð°Ð¿ÑÑмÑÑ ÑопоÑÑавиÑÑ Ñ Ð¿ÐµÑеменной-маÑÑивом ÑÑедÑ.
Ðожно Ñакже пÑимениÑÑ Ð¾Ð±Ñ
одное ÑеÑение â Ñ
ÑаниÑÑ Ð¼Ð°ÑÑÐ¸Ð²Ñ Ð² иÑ
внеÑнем ÑÑÑоковом пÑедÑÑавлении в пеÑеменнÑÑ
ÑÑÐµÐ´Ñ Ñипа char[] или VARCHAR[]. Ðолее подÑобно ÑÑо пÑедÑÑавление опиÑÑваеÑÑÑ Ð² ÐодÑазделе 8.15.2. ÐамеÑÑÑе, ÑÑо ознаÑаеÑ, ÑÑо Ñ Ñаким маÑÑивом в пÑогÑамме нелÑÐ·Ñ Ð±ÑÐ´ÐµÑ ÑабоÑаÑÑ ÐµÑÑеÑÑвеннÑм обÑазом (без дополниÑелÑного ÑазбоÑа ÑекÑÑового пÑедÑÑавлениÑ).
32.4.5.2. СоÑÑавнÑе ÑипÑ
СоÑÑавнÑе ÑÐ¸Ð¿Ñ Ð² ECPG напÑÑмÑÑ Ð½Ðµ поддеÑживаÑÑÑÑ, но еÑÑÑ Ð¿ÑоÑÑое Ð¾Ð±Ñ Ð¾Ð´Ð½Ð¾Ðµ ÑеÑение. ÐÐ»Ñ ÑеÑÐµÐ½Ð¸Ñ ÑÑой пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ пÑимениÑÑ Ñе же Ð¿Ð¾Ð´Ñ Ð¾Ð´Ñ, ÑÑо бÑли опиÑÐ°Ð½Ñ Ð²ÑÑе Ð´Ð»Ñ Ð¼Ð°ÑÑивов: обÑаÑаÑÑÑÑ Ðº ÐºÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð°ÑÑибÑÑÑ Ð¿Ð¾ оÑделÑноÑÑи или иÑполÑзоваÑÑ Ð²Ð½ÐµÑнее ÑÑÑоковое пÑедÑÑавление.
ÐÐ»Ñ ÑледÑÑÑÐ¸Ñ Ð¿ÑимеÑов пÑедполагаеÑÑÑ, ÑÑо ÑÑÑеÑÑвÑÐµÑ Ñакой Ñип и ÑаблиÑа:
CREATE TYPE comp_t AS (intval integer, textval varchar(32)); CREATE TABLE t4 (compval comp_t); INSERT INTO t4 VALUES ( (256, 'Postgres Pro') );
Самое оÑевидное ÑеÑение заклÑÑаеÑÑÑ Ð² обÑаÑении к ÐºÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð°ÑÑибÑÑÑ Ð¿Ð¾ оÑделÑноÑÑи. СледÑÑÑÐ°Ñ Ð¿ÑогÑамма полÑÑÐ°ÐµÑ Ð´Ð°Ð½Ð½Ñе из ÑеÑÑовой ÑаблиÑÑ, вÑбиÑÐ°Ñ Ð°ÑÑибÑÑÑ Ñипа comp_t по одномÑ:
EXEC SQL BEGIN DECLARE SECTION;
int intval;
varchar textval[33];
EXEC SQL END DECLARE SECTION;
/* УказаÑÑ ÐºÐ°Ð¶Ð´Ñй ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑÑолбÑа ÑоÑÑавного Ñипа в ÑпиÑке SELECT. */
EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).intval, (compval).textval FROM t4;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* ÐÑбÑаÑÑ ÐºÐ°Ð¶Ð´Ñй ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑÑолбÑа ÑоÑÑавного Ñипа в пеÑеменнÑÑ ÑÑÐµÐ´Ñ Ð¡. */
EXEC SQL FETCH FROM cur1 INTO :intval, :textval;
printf("intval=%d, textval=%s\n", intval, textval.arr);
}
EXEC SQL CLOSE cur1;Ð ÑазвиÑие ÑÑого пÑимеÑа, пеÑеменнÑе ÑÑедÑ, в коÑоÑÑе помеÑаÑÑÑÑ ÑезÑлÑÑаÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ FETCH, можно ÑобÑаÑÑ Ð² Ð¾Ð´Ð½Ñ ÑÑÑÑкÑÑÑÑ. ÐодÑобнее пеÑеменнÑе ÑÑÐµÐ´Ñ Ð² ÑоÑме ÑÑÑÑкÑÑÑÑ Ð¾Ð¿Ð¸ÑÑваÑÑÑÑ Ð² ÐодÑазделе 32.4.4.3.2. ЧÑÐ¾Ð±Ñ Ð¿ÐµÑейÑи к ÑÑÑÑкÑÑÑе, пÑÐ¸Ð¼ÐµÑ Ð¼Ð¾Ð¶Ð½Ð¾ измениÑÑ ÐºÐ°Ðº показано ниже. ÐеÑеменнÑе ÑÑедÑ, intval и textval, ÑÑановÑÑÑÑ Ñленами ÑÑÑÑкÑÑÑÑ comp_t, и ÑÑа ÑÑÑÑкÑÑÑа ÑказÑваеÑÑÑ Ð² команде FETCH.
EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
int intval;
varchar textval[33];
} comp_t;
comp_t compval;
EXEC SQL END DECLARE SECTION;
/* ÐомеÑÑиÑÑ ÐºÐ°Ð¶Ð´Ñй ÑÐ»ÐµÐ¼ÐµÐ½Ñ ÑоÑÑавного Ñипа в ÑпиÑок SELECT. */
EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).intval, (compval).textval FROM t4;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* ÐомеÑÑиÑÑ Ð²Ñе знаÑÐµÐ½Ð¸Ñ ÑпиÑка SELECT в Ð¾Ð´Ð½Ñ ÑÑÑÑкÑÑÑÑ. */
EXEC SQL FETCH FROM cur1 INTO :compval;
printf("intval=%d, textval=%s\n", compval.intval, compval.textval.arr);
}
EXEC SQL CLOSE cur1; ХоÑÑ Ð² команде FETCH иÑполÑзÑеÑÑÑ ÑÑÑÑкÑÑÑа, имена аÑÑибÑÑов в пÑедложении SELECT задаÑÑÑÑ Ð¿Ð¾ одномÑ. ÐÑо можно дополниÑелÑно ÑлÑÑÑиÑÑ, напиÑав *, ÑÑо бÑÐ´ÐµÑ Ð¾Ð±Ð¾Ð·Ð½Ð°ÑаÑÑ Ð²Ñе аÑÑибÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ ÑоÑÑавного Ñипа.
...
EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).* FROM t4;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
/* ÐÑбÑаÑÑ Ð²Ñе знаÑÐµÐ½Ð¸Ñ Ð² ÑпиÑке SELECT в Ð¾Ð´Ð½Ñ ÑÑÑÑкÑÑÑÑ. */
EXEC SQL FETCH FROM cur1 INTO :compval;
printf("intval=%d, textval=%s\n", compval.intval, compval.textval.arr);
}
...Таким обÑазом ÑоÑÑавнÑе ÑÐ¸Ð¿Ñ Ð¼Ð¾Ð¶Ð½Ð¾ ÑопоÑÑавиÑÑ Ñо ÑÑÑÑкÑÑÑами пÑакÑиÑеÑки пÑозÑаÑно, Ñ Ð¾ÑÑ ECPG и не Ð¿Ð¾Ð½Ð¸Ð¼Ð°ÐµÑ ÑоÑÑавнÑе ÑипÑ.
ÐаконеÑ, Ñакже можно ÑоÑ
ÑаниÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ ÑоÑÑавного Ñипа в иÑ
внеÑнем ÑÑÑоковом пÑедÑÑавлении в пеÑеменнÑÑ
ÑÑÐµÐ´Ñ Ñипа char[] или VARCHAR[]. Ðднако пÑи Ñаком подÑ
оде Ð½ÐµÑ Ð¿ÑоÑÑой возможноÑÑи обÑаÑаÑÑÑÑ Ð¸Ð· пÑогÑÐ°Ð¼Ð¼Ñ Ðº полÑм знаÑениÑ.
32.4.5.3. ÐолÑзоваÑелÑÑкие базовÑе ÑипÑ
ÐпÑеделÑемÑе полÑзоваÑелем базовÑе ÑÐ¸Ð¿Ñ Ð½Ðµ поддеÑживаÑÑÑÑ ECPG напÑÑмÑÑ. ÐÐ»Ñ Ð½Ð¸Ñ
можно иÑполÑзоваÑÑ Ð²Ð½ÐµÑнее ÑÑÑоковое пÑедÑÑавление и пеÑеменнÑе ÑÑÐµÐ´Ñ Ñипа char[] или VARCHAR[], и ÑÑо ÑеÑение дейÑÑвиÑелÑно бÑÐ´ÐµÑ Ð¿Ð¾Ð´Ñ
одÑÑим и доÑÑаÑоÑнÑм Ð´Ð»Ñ Ð±Ð¾Ð»ÑÑинÑÑва Ñипов.
СледÑÑÑий ÑÑÐ°Ð³Ð¼ÐµÐ½Ñ ÐºÐ¾Ð´Ð° демонÑÑÑиÑÑÐµÑ Ð¸ÑполÑзование Ñипа даннÑÑ
complex из пÑимеÑа в Разделе 34.11. ÐнеÑнее ÑÑÑоковое пÑедÑÑавление ÑÑого Ñипа Ð¸Ð¼ÐµÐµÑ ÑоÑÐ¼Ñ (%f,%f) и опÑеделено в ÑÑнкÑиÑÑ
complex_in() и complex_out() в Разделе 34.11. СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð²ÑÑавлÑÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð»ÐµÐºÑного Ñипа (1,1) и (3,3) в ÑÑолбÑÑ a и b, а заÑем вÑбиÑÐ°ÐµÑ Ð¸Ñ
из ÑаблиÑÑ.
EXEC SQL BEGIN DECLARE SECTION;
varchar a[64];
varchar b[64];
EXEC SQL END DECLARE SECTION;
EXEC SQL INSERT INTO test_complex VALUES ('(1,1)', '(3,3)');
EXEC SQL DECLARE cur1 CURSOR FOR SELECT a, b FROM test_complex;
EXEC SQL OPEN cur1;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (1)
{
EXEC SQL FETCH FROM cur1 INTO :a, :b;
printf("a=%s, b=%s\n", a.arr, b.arr);
}
EXEC SQL CLOSE cur1;ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð²ÑÐ²Ð¾Ð´Ð¸Ñ ÑледÑÑÑий ÑезÑлÑÑаÑ:
a=(1,1), b=(3,3)
ÐÑÑгое Ð¾Ð±Ñ Ð¾Ð´Ð½Ð¾Ðµ ÑеÑение ÑоÑÑÐ¾Ð¸Ñ Ð² Ñом, ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ³Ð°ÑÑ Ð¿ÑÑмого иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»ÑзоваÑелÑÑÐºÐ¸Ñ Ñипов в ECPG, а вмеÑÑо ÑÑого ÑоздаÑÑ ÑÑнкÑÐ¸Ñ Ð¸Ð»Ð¸ пÑиведение, вÑполнÑÑÑее пÑеобÑазование Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾Ð»ÑзоваÑелÑÑким Ñипом и пÑимиÑивнÑм Ñипом, коÑоÑÑй Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð±ÑабоÑаÑÑ ECPG. ÐамеÑÑÑе, однако, ÑÑо пÑÐ¸Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ñипов, оÑобенно неÑвнÑе, нÑжно добавлÑÑÑ Ð² ÑиÑÑÐµÐ¼Ñ Ñипов оÑÐµÐ½Ñ Ð¾ÑÑоÑожно.
ÐапÑимеÑ:
CREATE FUNCTION create_complex(r double, i double) RETURNS complex LANGUAGE SQL IMMUTABLE AS $$ SELECT $1 * complex '(1,0')' + $2 * complex '(0,1)' $$;
ÐоÑле Ñакого опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑледÑÑÑий код
EXEC SQL BEGIN DECLARE SECTION; double a, b, c, d; EXEC SQL END DECLARE SECTION; a = 1; b = 2; c = 3; d = 4; EXEC SQL INSERT INTO test_complex VALUES (create_complex(:a, :b), create_complex(:c, :d));
бÑÐ´ÐµÑ ÑабоÑаÑÑ Ñак же, как
EXEC SQL INSERT INTO test_complex VALUES ('(1,2)', '(3,4)');32.4.6. ÐндикаÑоÑÑ
ÐÑиведÑннÑе вÑÑе пÑимеÑÑ Ð½Ð¸ÐºÐ°Ðº не обÑабаÑÑвали знаÑÐµÐ½Ð¸Ñ NULL. Ðа Ñамом деле, в пÑимеÑÐ°Ñ Ñ Ð¸Ð·Ð²Ð»ÐµÑением даннÑÑ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÐµÑ Ð¾Ñибка, еÑли они вÑбеÑÑÑ Ð¸Ð· Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ Ð·Ð½Ð°Ñение NULL. ЧÑÐ¾Ð±Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑло пеÑедаваÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NULL в Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¸Ð»Ð¸ полÑÑаÑÑ Ð¸Ñ Ð¸Ð· Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ , Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸ÑÑ Ð¾Ð±ÑÑвление вÑоÑой пеÑеменной ÑÑÐµÐ´Ñ C Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ пеÑеменной C, ÑодеÑжаÑей даннÑе. ÐÑа вÑоÑÐ°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ ÑÑÐµÐ´Ñ C назÑваеÑÑÑ Ð¸Ð½Ð´Ð¸ÐºÐ°ÑоÑом и ÑодеÑÐ¶Ð¸Ñ Ñлаг, показÑваÑÑий, ÑÑо в даннÑÑ Ð¿ÐµÑедаÑÑÑÑ NULL, и пÑи ÑÑом знаÑение оÑновной пеÑеменной ÑÑÐµÐ´Ñ C игноÑиÑÑеÑÑÑ. СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑиÑÑÐµÑ Ð¿ÑавилÑнÑÑ Ð¾Ð±ÑабоÑÐºÑ Ð·Ð½Ð°Ñений NULL:
EXEC SQL BEGIN DECLARE SECTION; VARCHAR val; int val_ind; EXEC SQL END DECLARE SECTION: ... EXEC SQL SELECT b INTO :val :val_ind FROM test1;
ÐеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð½Ð´Ð¸ÐºÐ°ÑоÑа val_ind бÑÐ´ÐµÑ Ñавна нÑлÑ, еÑли знаÑение не NULL, или оÑÑиÑаÑелÑÐ½Ð¾Ð¼Ñ ÑиÑлÑ, еÑли NULL.
ÐндикаÑÐ¾Ñ Ð²ÑполнÑÐµÑ ÐµÑÑ Ð¾Ð´Ð½Ñ ÑÑнкÑиÑ: еÑли он ÑодеÑÐ¶Ð¸Ñ Ð¿Ð¾Ð»Ð¾Ð¶Ð¸ÑелÑное ÑиÑло, ÑÑо ознаÑаеÑ, ÑÑо знаÑение не NULL, но оно бÑло обÑезано, когда ÑÐ¾Ñ ÑанÑлоÑÑ Ð² пеÑеменной ÑÑÐµÐ´Ñ Ð¡.
ÐÑли пÑепÑоÑеÑÑоÑÑ ecpg пеÑедаÑÑÑÑ Ð°ÑгÑÐ¼ÐµÐ½Ñ -r no_indicator, он ÑабоÑÐ°ÐµÑ Ð² Ñежиме «без индикаÑоÑа». Ð ÑÑом Ñежиме, еÑли пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð½Ð´Ð¸ÐºÐ°ÑоÑа не опÑеделена, знаÑÐµÐ½Ð¸Ñ NULL обознаÑаÑÑÑÑ (пÑи вводе и вÑводе) Ð´Ð»Ñ ÑимволÑнÑÑ
ÑÑÑок пÑÑÑой ÑÑÑокой, а Ð´Ð»Ñ ÑелоÑиÑленнÑÑ
Ñипов наименÑÑим возможнÑм знаÑением ÑÑого Ñипа (напÑимеÑ, INT_MIN Ð´Ð»Ñ int).