55.2. Создание неÑÑандаÑÑнÑÑ Ð¿Ð»Ð°Ð½Ð¾Ð² ÑканиÑованиÑ
ÐеÑÑандаÑÑное ÑканиÑование пÑедÑÑавлÑеÑÑÑ Ð² оконÑаÑелÑном деÑеве плана в виде ÑледÑÑÑей ÑÑÑÑкÑÑÑÑ:
typedef struct CustomScan
{
Scan scan;
uint32 flags;
List *custom_plans;
List *custom_exprs;
List *custom_private;
List *custom_scan_tlist;
Bitmapset *custom_relids;
const CustomScanMethods *methods;
} CustomScan;ÐбÑÐµÐºÑ Ð² поле scan должен бÑÑÑ Ð¸Ð½Ð¸ÑиализиÑован, как и Ð´Ð»Ñ Ð»Ñбого дÑÑгого ÑканиÑованиÑ, и вклÑÑаÑÑ Ð¾Ñенки ÑÑоимоÑÑи, ÑелевÑе ÑпиÑки, ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ Ñ. д. Ðоле flags ÑодеÑÐ¶Ð¸Ñ Ð±Ð¸ÑовÑÑ Ð¼Ð°ÑÐºÑ Ñ Ñем же знаÑением, ÑÑо и в CustomPath. Рполе custom_plans могÑÑ Ð±ÑÑÑ ÑоÑ
ÑÐ°Ð½ÐµÐ½Ñ Ð´Ð¾ÑеÑние ÑÐ·Ð»Ñ Plan. Ð custom_exprs могÑÑ Ð±ÑÑÑ ÑоÑ
ÑÐ°Ð½ÐµÐ½Ñ Ð´ÐµÑевÑÑ Ð²ÑÑажений, коÑоÑÑе бÑдÑÑ Ð¸ÑпÑавлÑÑÑÑÑ ÐºÐ¾Ð´Ð¾Ð¼ в setrefs.c и subselect.c, а в custom_private ÑледÑÐµÑ ÑоÑ
ÑаниÑÑ Ð´ÑÑгие внÑÑÑенние даннÑе, коÑоÑÑе бÑдÑÑ Ð¸ÑполÑзоваÑÑÑÑ ÑолÑко Ñамим пÑовайдеÑом неÑÑандаÑÑного ÑканиÑованиÑ. Ðоле custom_scan_tlist Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ NIL пÑи ÑканиÑовании базового оÑноÑениÑ, ÑÑо бÑÐ´ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑваÑÑ, ÑÑо неÑÑандаÑÑное ÑканиÑование возвÑаÑÐ°ÐµÑ ÐºÐ¾ÑÑежи, ÑооÑвеÑÑÑвÑÑÑие ÑÐ¸Ð¿Ñ ÑÑÑок базового оÑноÑениÑ. РпÑоÑивном ÑлÑÑае оно должно ÑказÑваÑÑ Ð½Ð° Ñелевой ÑпиÑок, опиÑÑваÑÑий ÑакÑиÑеÑкие коÑÑежи. СпиÑок custom_scan_tlist должен ÑÑÑанавливаÑÑÑÑ Ð¿Ñи ÑоединениÑÑ
и Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð´Ð°Ð²Ð°ÑÑÑÑ Ð¿Ñи ÑканиÑовании, еÑли пÑÐ¾Ð²Ð°Ð¹Ð´ÐµÑ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²ÑÑиÑлÑÑÑ ÐºÐ°ÐºÐ¸Ðµ-либо вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð±ÐµÐ· пеÑеменнÑÑ
. Ðоле custom_relids заполнÑеÑÑÑ ÑдÑом и задаÑÑ Ð½Ð°Ð±Ð¾Ñ Ð¾ÑноÑений (индекÑов в ÑпиÑке оÑноÑений), коÑоÑÑе обÑабаÑÑÐ²Ð°ÐµÑ Ð´Ð°Ð½Ð½Ñй Ñзел ÑканиÑованиÑ; когда Ð¸Ð¼ÐµÐµÑ Ð¼ÐµÑÑо ÑканиÑование, а не Ñоединение, в ÑÑом ÑпиÑке бÑÐ´ÐµÑ Ð²Ñего один ÑлеменÑ. Ðоле methods должно ÑказÑваÑÑ Ð½Ð° обÑÐµÐºÑ (обÑÑно ÑÑаÑиÑеÑки ÑазмеÑÑннÑй), ÑеализÑÑÑий ÑÑебÑемÑе меÑÐ¾Ð´Ñ Ð½ÐµÑÑандаÑÑного ÑканиÑованиÑ, коÑоÑÑе подÑобнее опиÑÑваÑÑÑÑ Ð½Ð¸Ð¶Ðµ.
Ðогда CustomScan ÑканиÑÑÐµÑ Ð¾Ð´Ð½Ð¾ оÑноÑение, в scan.scanrelid должен задаваÑÑÑÑ Ð¸Ð½Ð´ÐµÐºÑ ÑканиÑÑемой ÑаблиÑÑ Ð² ÑпиÑке оÑноÑений. Ðогда он заменÑÐµÑ Ñоединение, поле scan.scanrelid должно бÑÑÑ Ð½ÑлевÑм.
ÐеÑевÑÑ Ð¿Ð»Ð°Ð½Ð¾Ð² Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð´Ð´ÐµÑживаÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ ÐºÐ¾Ð¿Ð¸ÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑÑнкÑией copyObject, Ñак ÑÑо вÑе даннÑе, ÑоÑ
ÑанÑннÑе в «дополниÑелÑнÑÑ
» полÑÑ
, Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ñзлами, коÑоÑÑе Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð±ÑабоÑаÑÑ ÑÑа ÑÑнкÑиÑ. Ðолее Ñого, пÑовайдеÑÑ Ð½ÐµÑÑандаÑÑного ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ могÑÑ Ð·Ð°Ð¼ÐµÐ½ÑÑÑ ÑÑÑÑкÑÑÑÑ CustomScan ÑаÑÑиÑенной ÑÑÑÑкÑÑÑой, ÐµÑ ÑодеÑжаÑей, ÑÑо возможно Ñ CustomPath или CustomScanState.
55.2.1. ÐбÑабоÑÑики плана неÑÑандаÑÑного ÑканиÑованиÑ
Node *(*CreateCustomScanState) (CustomScan *cscan);
ÐÑделÑÐµÑ ÑÑÑÑкÑÑÑÑ CustomScanState Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ обÑекÑа CustomScan. ФакÑиÑеÑки вÑÐ´ÐµÐ»ÐµÐ½Ð½Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑÑ Ð±ÑÐ´ÐµÑ Ð¾Ð±ÑÑно болÑÑе, Ñем ÑÑебÑеÑÑÑ Ð´Ð»Ñ Ñамой ÑÑÑÑкÑÑÑÑ CustomScanState, Ñак как многие пÑовайдеÑÑ Ð¼Ð¾Ð³ÑÑ Ð²ÐºÐ»ÑÑаÑÑ ÐµÑ Ð² ÑаÑÑиÑеннÑÑ ÑÑÑÑкÑÑÑÑ Ð² каÑеÑÑве пеÑвого полÑ. РвозвÑаÑаемом знаÑении Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¿Ð¾Ð´Ñ
одÑÑим обÑазом Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ñ Ñег Ñзла и поле methods, но дÑÑгие Ð¿Ð¾Ð»Ñ Ð½Ð° данном ÑÑапе Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¾Ð±Ð½ÑленÑ; поÑле Ñого как ExecInitCustomScan пÑоизведÑÑ Ð±Ð°Ð·Ð¾Ð²ÑÑ Ð¸Ð½Ð¸ÑиализаÑиÑ, бÑÐ´ÐµÑ Ð²Ñзван обÑабоÑÑик BeginCustomScan, в коÑоÑом пÑÐ¾Ð²Ð°Ð¹Ð´ÐµÑ Ð½ÐµÑÑандаÑÑного ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²ÑполниÑÑ Ð²Ñе оÑÑалÑнÑе ÑÑебÑемÑе дейÑÑвиÑ.