ส่วนขยายนี้เป็น linter เต็มรูปแบบสำหรับ PLPGSQL สำหรับ postgreSQL มันใช้ประโยชน์เฉพาะตัวแยกวิเคราะห์/ผู้ประเมินผล postgreSQL ภายในเท่านั้นดังนั้นคุณจะเห็นข้อผิดพลาดที่จะเกิดขึ้นในเวลารันไทม์ นอกจากนี้ยังวิเคราะห์ SQL ภายในกิจวัตรของคุณและพบข้อผิดพลาดที่ไม่พบในระหว่างคำสั่ง "สร้างขั้นตอน/ฟังก์ชั่น" คุณสามารถควบคุมระดับของคำเตือนและคำแนะนำมากมาย ในที่สุดคุณสามารถเพิ่มเครื่องหมายประเภท Pragama เพื่อปิด/ในหลาย ๆ ด้านช่วยให้คุณซ่อนข้อความที่คุณรู้อยู่แล้วหรือเตือนให้คุณกลับมาทำความสะอาดลึกลงไปในภายหลัง
ฉันก่อตั้งโครงการนี้เพราะฉันต้องการเผยแพร่รหัสที่ฉันเขียนเป็นเวลาสองปีเมื่อฉันพยายามเขียนการตรวจสอบขั้นสูงสำหรับ PostgreSQL ต้นน้ำ มันไม่ประสบความสำเร็จอย่างเต็มที่ - การรวมเข้ากับต้นน้ำต้องใช้การปรับโครงสร้าง PLPGSQL ขนาดใหญ่ขึ้น แต่รหัสนั้นใช้งานได้อย่างสมบูรณ์และสามารถใช้ในการผลิต (และใช้ในการผลิต) ดังนั้นฉันจึงสร้างส่วนขยายนี้ให้พร้อมสำหรับนักพัฒนา PLPGSQL ทั้งหมด
หากคุณต้องการเข้าร่วมกลุ่มของเราเพื่อช่วยในการพัฒนาส่วนขยายนี้ให้ลงทะเบียนตัวเองที่การแฮ็กส่วนขยายของ PostgreSQL Google Group
ฉันเชิญความคิดใด ๆ แพตช์ bugreports
รองรับ PostgreSQL PostgreSQL 12 - 17
คำสั่ง SQL ภายในฟังก์ชั่น PL/PGSQL ถูกตรวจสอบโดยผู้ตรวจสอบความถูกต้องสำหรับข้อผิดพลาดทางความหมาย ข้อผิดพลาดเหล่านี้สามารถพบได้โดยเรียก PLPGSQL_CHECK_FUNCTION:
postgres=# CREATE EXTENSION plpgsql_check;
LOAD
postgres=# CREATE TABLE t1(a int, b int);
CREATE TABLE
postgres=#
CREATE OR REPLACE FUNCTION public.f1()
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE r record;
BEGIN
FOR r IN SELECT * FROM t1
LOOP
RAISE NOTICE '%', r.c; -- there is bug - table t1 missing "c" column
END LOOP;
END;
$function$;
CREATE FUNCTION
postgres=# select f1(); -- execution doesn't find a bug due to empty table t1
f1
────
(1 row)
postgres=# x
Expanded display is on.
postgres=# select * from plpgsql_check_function_tb('f1()');
─[ RECORD 1 ]───────────────────────────
functionid │ f1
lineno │ 6
statement │ RAISE
sqlstate │ 42703
message │ record "r" has no field "c"
detail │ [null]
hint │ [null]
level │ error
position │ 0
query │ [null]
postgres=# sf+ f1
CREATE OR REPLACE FUNCTION public.f1()
RETURNS void
LANGUAGE plpgsql
1 AS $function$
2 DECLARE r record;
3 BEGIN
4 FOR r IN SELECT * FROM t1
5 LOOP
6 RAISE NOTICE '%', r.c; -- there is bug - table t1 missing "c" column
7 END LOOP;
8 END;
9 $function$
ฟังก์ชั่น plpgsql_check_function () มีสามรูปแบบเอาต์พุตที่เป็นไปได้: ข้อความ, json หรือ xml
select * from plpgsql_check_function('f1()', fatal_errors := false);
plpgsql_check_function
------------------------------------------------------------------------
error:42703:4:SQL statement:column "c" of relation "t1" does not exist
Query: update t1 set c = 30
-- ^
error:42P01:7:RAISE:missing FROM-clause entry for table "r"
Query: SELECT r.c
-- ^
error:42601:7:RAISE:too few parameters specified for RAISE
(7 rows)
postgres=# select * from plpgsql_check_function('fx()', format:='xml');
plpgsql_check_function
────────────────────────────────────────────────────────────────
<Function oid="16400"> ↵
<Issue> ↵
<Level>error</level> ↵
<Sqlstate>42P01</Sqlstate> ↵
<Message>relation "foo111" does not exist</Message> ↵
<Stmt lineno="3">RETURN</Stmt> ↵
<Query position="23">SELECT (select a from foo111)</Query>↵
</Issue> ↵
</Function>
(1 row)
คุณสามารถตั้งค่าระดับคำเตือนผ่านพารามิเตอร์ของฟังก์ชั่น:
funcoid oid - ชื่อฟังก์ชั่นหรือลายเซ็นฟังก์ชั่น - ฟังก์ชั่นต้องการข้อมูลจำเพาะฟังก์ชัน ฟังก์ชั่นใด ๆ ใน PostgreSQL สามารถระบุได้โดย OID หรือตามชื่อหรือตามลายเซ็น เมื่อคุณรู้ว่าลายเซ็นของ OID หรือฟังก์ชั่นที่สมบูรณ์คุณสามารถใช้พารามิเตอร์ประเภท RegProcedure เช่น 'fx()'::regprocedure หรือ 16799::regprocedure ทางเลือกที่เป็นไปได้คือการใช้ชื่อเท่านั้นเมื่อชื่อของฟังก์ชั่นไม่ซ้ำกัน - เช่น 'fx' เมื่อชื่อไม่ซ้ำกันหรือฟังก์ชั่นไม่มีอยู่มันจะทำให้เกิดข้อผิดพลาด relid DEFAULT 0 - oid ของความสัมพันธ์ที่กำหนดด้วยฟังก์ชันทริกเกอร์ จำเป็นต้องตรวจสอบฟังก์ชั่นทริกเกอร์ใด ๆ คุณกำลังส่งตารางที่ทริกเกอร์ทำงานอยู่
fatal_errors boolean DEFAULT true - หยุดข้อผิดพลาดแรก (ป้องกันรายงานข้อผิดพลาดจำนวนมาก)
other_warnings boolean DEFAULT true - แสดงคำเตือนเช่นหมายเลขแอตทริบิวต์ที่แตกต่างกันใน AssignMenet ทางด้านซ้ายและด้านขวาพารามิเตอร์ฟังก์ชันการทับซ้อนของตัวแปรตัวแปรที่ไม่ได้ใช้การหล่อที่ไม่พึงประสงค์ ฯลฯ
extra_warnings boolean DEFAULT true - แสดงคำเตือนเช่น RETURN ตัวแปรที่ไม่มีเงา, รหัสที่ตายแล้ว, ไม่อ่าน (ไม่ได้ใช้) พารามิเตอร์ของฟังก์ชั่นฟังก์ชัน, ตัวแปรที่ไม่ได้แก้ไข, ตัวแปรอัตโนมัติที่ได้รับการแก้ไข ฯลฯ
performance_warnings boolean DEFAULT false - คำเตือนที่เกี่ยวข้องกับประสิทธิภาพเช่นประเภทที่ประกาศด้วยตัวดัดแปลงประเภทการคัดเลือกนักแสดงโดยปริยายในกรณีที่ประโยค (อาจเป็นเหตุผลว่าทำไมดัชนีไม่ได้ใช้) ฯลฯ
security_warnings boolean DEFAULT false - การตรวจสอบความปลอดภัยที่เกี่ยวข้องเช่นการตรวจจับช่องโหว่การฉีด SQL
compatibility_warnings boolean DEFAULT false - การตรวจสอบที่เกี่ยวข้องกับความเข้ากันได้เช่นการตั้งค่าเคอร์เซอร์ภายในที่ล้าสมัยอย่างชัดเจนในตัวแปร refcursor หรือตัวแปรของเคอร์เซอร์
anyelementtype regtype DEFAULT 'int' - ประเภทจริงที่จะใช้เมื่อทดสอบประเภท anyelement
anyenumtype regtype DEFAULT '-' - ประเภทจริงที่จะใช้เมื่อทดสอบประเภท anyenum
anyrangetype regtype DEFAULT 'int4range' - ประเภทจริงที่จะใช้เมื่อทดสอบประเภท anyrange
anycompatibletype DEFAULT 'int' - ประเภทจริงที่จะใช้เมื่อทดสอบประเภทใด ๆ ที่เข้ากันได้
anycompatiblerangetype DEFAULT 'int4range' - ประเภทช่วงจริงที่จะใช้เมื่อทดสอบประเภทช่วงที่เข้ากันได้
without_warnings DEFAULT false - ปิดใช้งานคำเตือนทั้งหมด (ละเว้นพารามิเตอร์ xxxxx_warning ทั้งหมดการแทนที่อย่างรวดเร็ว)
all_warnings DEFAULT false - เปิดใช้งานคำเตือนทั้งหมด (ละเว้นพารามิเตอร์ xxx_warning อื่น ๆ เป็นบวกอย่างรวดเร็ว)
newtable DEFAULT NULL , oldtable DEFAULT NULL - ชื่อของตารางการเปลี่ยนแปลงใหม่หรือเก่า พารามิเตอร์เหล่านี้จำเป็นเมื่อใช้ตารางการเปลี่ยนแปลงในฟังก์ชันทริกเกอร์
use_incomment_options DEFAULT true - เมื่อเป็นจริงตัวเลือกในการเปิดเครื่องจะใช้งานอยู่
incomment_options_usage_warning DEFAULT false - เมื่อเป็นจริงการเตือนจะเพิ่มขึ้นเมื่อใช้ตัวเลือกการเข้าร่วม
constant_tracing boolean DEFAULT true - เมื่อเป็นจริงตัวแปรที่เก็บเนื้อหาคงที่บางอย่างสามารถใช้งานได้เช่นค่าคงที่ (ทำงานเฉพาะในบางกรณีง่าย ๆ และเนื้อหาของตัวแปรไม่ควรคลุมเครือ)
เมื่อคุณต้องการตรวจสอบทริกเกอร์ใด ๆ คุณต้องป้อนความสัมพันธ์ที่จะใช้ร่วมกับฟังก์ชันทริกเกอร์
CREATE TABLE bar(a int, b int);
postgres=# sf+ foo_trg
CREATE OR REPLACE FUNCTION public.foo_trg()
RETURNS trigger
LANGUAGE plpgsql
1 AS $function$
2 BEGIN
3 NEW.c := NEW.a + NEW.b;
4 RETURN NEW;
5 END;
6 $function$
สเปคความสัมพันธ์ที่ขาดหายไป
postgres=# select * from plpgsql_check_function('foo_trg()');
ERROR: missing trigger relation
HINT: Trigger relation oid must be valid
ตรวจสอบทริกเกอร์ที่ถูกต้อง (พร้อมความสัมพันธ์ที่ระบุ)
postgres=# select * from plpgsql_check_function('foo_trg()', 'bar');
plpgsql_check_function
--------------------------------------------------------
error:42703:3:assignment:record "new" has no field "c"
(1 row)
สำหรับทริกเกอร์ด้วยตารางสกรรมกริยาคุณสามารถตั้งค่าพารามิเตอร์ oldtable และ newtable :
create or replace function footab_trig_func()
returns trigger as $$
declare x int;
begin
if false then
-- should be ok;
select count(*) from newtab into x;
-- should fail;
select count(*) from newtab where d = 10 into x;
end if;
return null;
end;
$$ language plpgsql;
select * from plpgsql_check_function('footab_trig_func','footab', newtable := 'newtab');
plpgsql_check อนุญาตให้ตั้งค่าถาวรที่เขียนในความคิดเห็น ตัวเลือกเหล่านี้มาจากซอร์สโค้ดของฟังก์ชั่นก่อนตรวจสอบ ไวยากรณ์คือ:
@plpgsql_check_option: optioname [=] value [, optname [=] value ...]
การตั้งค่าจากตัวเลือกความคิดเห็นมีลำดับความสำคัญสูงที่สุด แต่โดยทั่วไปแล้วสามารถปิดใช้งานได้โดยตัวเลือก use_incomment_options เป็น false
ตัวอย่าง:
create or replace function fx(anyelement)
returns text as $$
begin
/*
* rewrite default polymorphic type to text
* @plpgsql_check_options: anyelementtype = text
*/
return $1;
end;
$$ language plpgsql;
คุณสามารถใช้ plpgsql_check_function สำหรับการตรวจสอบจำนวนมากของฟังก์ชั่น/ขั้นตอนและการตรวจสอบมวลของทริกเกอร์ กรุณาทดสอบคำค้นหาต่อไปนี้:
-- check all nontrigger plpgsql functions
SELECT p.oid, p.proname, plpgsql_check_function(p.oid)
FROM pg_catalog.pg_namespace n
JOIN pg_catalog.pg_proc p ON pronamespace = n.oid
JOIN pg_catalog.pg_language l ON p.prolang = l.oid
WHERE l.lanname = 'plpgsql' AND p.prorettype <> 2279;
หรือ
-- check all trigger plpgsql functions
SELECT p.proname, tgrelid::regclass, cf.*
FROM pg_proc p
JOIN pg_trigger t ON t.tgfoid = p.oid
JOIN pg_language l ON p.prolang = l.oid
JOIN pg_namespace n ON p.pronamespace = n.oid,
LATERAL plpgsql_check_function(p.oid, t.tgrelid) cf
WHERE n.nspname = 'public' and l.lanname = 'plpgsql';
หรือ
-- check all plpgsql functions (functions or trigger functions with defined triggers)
SELECT
(pcf).functionid::regprocedure, (pcf).lineno, (pcf).statement,
(pcf).sqlstate, (pcf).message, (pcf).detail, (pcf).hint, (pcf).level,
(pcf)."position", (pcf).query, (pcf).context
FROM
(
SELECT
plpgsql_check_function_tb(pg_proc.oid, COALESCE(pg_trigger.tgrelid, 0)) AS pcf
FROM pg_proc
LEFT JOIN pg_trigger
ON (pg_trigger.tgfoid = pg_proc.oid)
WHERE
prolang = (SELECT lang.oid FROM pg_language lang WHERE lang.lanname = 'plpgsql') AND
pronamespace <> (SELECT nsp.oid FROM pg_namespace nsp WHERE nsp.nspname = 'pg_catalog') AND
-- ignore unused triggers
(pg_proc.prorettype <> (SELECT typ.oid FROM pg_type typ WHERE typ.typname = 'trigger') OR
pg_trigger.tgfoid IS NOT NULL)
OFFSET 0
) ss
ORDER BY (pcf).functionid::regprocedure::text, (pcf).lineno;
ฟังก์ชั่นสามารถตรวจสอบได้เมื่อต้องดำเนินการ - โมดูล PLPGSQL_CHECK จะต้องโหลด (ผ่าน PostgreSQL.Conf)
plpgsql_check.mode = [ disabled | by_function | fresh_start | every_start ]
plpgsql_check.fatal_errors = [ yes | no ]
plpgsql_check.show_nonperformance_warnings = false
plpgsql_check.show_performance_warnings = false
โหมดเริ่มต้นคือ by_function นั่นหมายความว่าการตรวจสอบขั้นสูงจะทำเฉพาะในโหมดที่ใช้งานอยู่ - โดยการเรียก plpgsql_check_function fresh_start หมายถึงการเริ่มต้นเย็น (ก่อนอื่นเรียกว่าฟังก์ชั่น)
คุณสามารถเปิดใช้งานโหมดแฝงได้โดย
load 'plpgsql'; -- 1.1 and higher doesn't need it
load 'plpgsql_check';
set plpgsql_check.mode = 'every_start'; -- This scans all code before it is executed
SELECT fx(10); -- run functions - function is checked before runtime starts it
ตัวแปร PostgreSQL Cursor และตัวแปรของ Refcursor เป็นตัวแปรสตริงที่ได้รับการปรับปรุงซึ่งมีชื่อเฉพาะของพอร์ทัลที่เกี่ยวข้อง (โครงสร้างภายในของ postgres ที่ใช้สำหรับการใช้งานของเคอร์เซอร์) จนกระทั่ง PostgreSQL 16 พอร์ทัลมีชื่อเดียวกันเช่นชื่อของตัวแปรเคอร์เซอร์ PostgreSQL 16 และการเปลี่ยนแปลงที่สูงขึ้นกลไกนี้และโดยค่าเริ่มต้นพอร์ทัลที่เกี่ยวข้องจะถูกตั้งชื่อโดยชื่อที่ไม่ซ้ำกัน มันแก้ปัญหาบางอย่างด้วยเคอร์เซอร์ในบล็อกซ้อนกันหรือเมื่อใช้เคอร์เซอร์ในการเรียกใช้ฟังก์ชั่นที่เรียกว่า
ด้วยการเปลี่ยนแปลงที่กล่าวถึงตัวแปร refcursor ควรใช้ค่าจากตัวแปร refcursor อื่นหรือจากตัวแปรเคอร์เซอร์บางตัว (เมื่อเปิดเคอร์เซอร์)
-- obsolete pattern
DECLARE
cur CURSOR FOR SELECT 1;
rcur refcursor;
BEGIN
rcur := 'cur';
OPEN cur;
...
-- new pattern
DECLARE
cur CURSOR FOR SELECT 1;
rcur refcursor;
BEGIN
OPEN cur;
rcur := cur;
...
เมื่อ Flag compatibility_warnings เปิดใช้งานแล้ว plpgsql_check พยายามระบุการกำหนดคาวชิงให้กับตัวแปร refcursor หรือการส่งคืนค่าของ refcursor:
CREATE OR REPLACE FUNCTION public.foo()
RETURNS refcursor
AS $$
declare
c cursor for select 1;
r refcursor;
begin
open c;
r := 'c';
return r;
end;
$$ LANGUAGE plpgsql;
select * from plpgsql_check_function('foo', extra_warnings =>false, compatibility_warnings => true);
┌───────────────────────────────────────────────────────────────────────────────────┐
│ plpgsql_check_function │
╞═══════════════════════════════════════════════════════════════════════════════════╡
│ compatibility:00000:6:assignment:obsolete setting of refcursor or cursor variable │
│ Detail: Internal name of cursor should not be specified by users. │
│ Context: at assignment to variable "r" declared on line 3 │
└───────────────────────────────────────────────────────────────────────────────────┘
(3 rows)
PLPGSQL_CHECK ควรค้นหาข้อผิดพลาดเกือบทั้งหมดในรหัสคงที่จริงๆ เมื่อนักพัฒนาใช้คุณสมบัติแบบไดนามิกของ PLPGSQL เช่น SQL แบบไดนามิกหรือประเภทข้อมูลบันทึกข้อมูลที่เป็นเท็จจะเป็นไปได้ สิ่งเหล่านี้ควรหายาก - ในรหัสที่เขียนได้ดี - จากนั้นฟังก์ชั่นที่ได้รับผลกระทบควรได้รับการออกแบบใหม่หรือ PLPGSQL_CHECK ควรปิดการใช้งานสำหรับฟังก์ชั่นนี้
CREATE OR REPLACE FUNCTION f1()
RETURNS void AS $$
DECLARE r record;
BEGIN
FOR r IN EXECUTE 'SELECT * FROM t1'
LOOP
RAISE NOTICE '%', r.c;
END LOOP;
END;
$$ LANGUAGE plpgsql SET plpgsql.enable_check TO false;
การใช้ PLPGSQL_CHECK เพิ่มค่าใช้จ่ายขนาดเล็ก (เมื่อเปิดใช้งานโหมดแฝง) และคุณควรใช้การตั้งค่านั้นเฉพาะในการพัฒนาหรือสภาพแวดล้อมการเตรียมการล่วงหน้า
โมดูลนี้ไม่ได้ตรวจสอบแบบสอบถามที่ประกอบในรันไทม์ เป็นไปไม่ได้ที่จะระบุผลลัพธ์ของการสืบค้นแบบไดนามิก - ดังนั้น PLPGSQL_CHECK ไม่สามารถตั้งค่าประเภทที่ถูกต้องเพื่อบันทึกตัวแปรและไม่สามารถตรวจสอบ SQL และนิพจน์ที่ขึ้นอยู่กับ
เมื่อประเภทของตัวแปรบันทึกไม่ทราบคุณสามารถกำหนดได้อย่างชัดเจนกับ type pragma:
DECLARE r record;
BEGIN
EXECUTE format('SELECT * FROM %I', _tablename) INTO r;
PERFORM plpgsql_check_pragma('type: r (id int, processed bool)');
IF NOT r.processed THEN
...
PLPGSQL_CHECK ไม่สามารถใช้เพื่อตรวจจับโครงสร้างของเคอร์เซอร์ที่อ้างอิง การอ้างอิงเกี่ยวกับเคอร์เซอร์ใน PLPGSQL ถูกนำมาใช้เป็นชื่อของเคอร์เซอร์ทั่วโลก ในเวลาตรวจสอบชื่อไม่เป็นที่รู้จัก (ไม่ได้อยู่ในความเป็นไปได้ทั้งหมด) และเคอร์เซอร์ทั่วโลกไม่มีอยู่ มันเป็นปัญหาที่สำคัญสำหรับการวิเคราะห์แบบคงที่ใด ๆ PLPGSQL ไม่สามารถทราบวิธีการตั้งค่าประเภทที่ถูกต้องสำหรับตัวแปรบันทึกและไม่สามารถตรวจสอบคำสั่งและนิพจน์ SQL ที่ขึ้นอยู่กับ วิธีแก้ปัญหาเหมือนกันสำหรับ SQL แบบไดนามิก อย่าใช้ตัวแปรเร็กคอร์ดเป็นเป้าหมายเมื่อคุณใช้ประเภท Refcursor หรือปิดการใช้งาน PLPGSQL_CHECK สำหรับฟังก์ชั่นเหล่านี้
CREATE OR REPLACE FUNCTION foo(refcur_var refcursor)
RETURNS void AS $$
DECLARE
rec_var record;
BEGIN
FETCH refcur_var INTO rec_var; -- this is STOP for plpgsql_check
RAISE NOTICE '%', rec_var; -- record rec_var is not assigned yet error
ในกรณีนี้ไม่ควรใช้ประเภทบันทึก (ใช้ RowType ที่รู้จักแทน):
CREATE OR REPLACE FUNCTION foo(refcur_var refcursor)
RETURNS void AS $$
DECLARE
rec_var some_rowtype;
BEGIN
FETCH refcur_var INTO rec_var;
RAISE NOTICE '%', rec_var;
PLPGSQL_CHECK ไม่สามารถตรวจสอบการสืบค้นผ่านตารางชั่วคราวที่สร้างขึ้นในฟังก์ชั่นของ PLPGSQL สำหรับกรณีการใช้งานนี้จำเป็นต้องสร้างตารางอุณหภูมิปลอมหรือปิดใช้งาน PLPGSQL_CHECK สำหรับฟังก์ชั่นนี้
ในความเป็นจริงตารางอุณหภูมิจะถูกเก็บไว้ในสคีมา (ต่อผู้ใช้) ของตัวเองที่มีลำดับความสำคัญสูงกว่าตารางถาวร ดังนั้นคุณสามารถทำได้ (ด้วยเคล็ดลับต่อไปนี้อย่างปลอดภัย):
CREATE OR REPLACE FUNCTION public.disable_dml()
RETURNS trigger
LANGUAGE plpgsql AS $function$
BEGIN
RAISE EXCEPTION SQLSTATE '42P01'
USING message = format('this instance of %I table doesn''t allow any DML operation', TG_TABLE_NAME),
hint = format('you should use "CREATE TEMP TABLE %1$I(LIKE %1$I INCLUDING ALL);" statement',
TG_TABLE_NAME);
RETURN NULL;
END;
$function$;
CREATE TABLE foo(a int, b int); -- doesn't hold data, ever
CREATE TRIGGER foo_disable_dml
BEFORE INSERT OR UPDATE OR DELETE ON foo
EXECUTE PROCEDURE disable_dml();
postgres=# INSERT INTO foo VALUES(10,20);
ERROR: this instance of foo table doesn't allow any DML operation
HINT: you should to run "CREATE TEMP TABLE foo(LIKE foo INCLUDING ALL);" statement
postgres=#
CREATE TABLE
postgres=# INSERT INTO foo VALUES(10,20);
INSERT 0 1
เคล็ดลับนี้เลียนแบบตารางอุณหภูมิทั่วโลกบางส่วนและอนุญาตให้มีการตรวจสอบความถูกต้องตามสถิติ ความเป็นไปได้อื่น ๆ คือการใช้ [wrapper ข้อมูลต่างประเทศ] (https://github.com/okbob/template_fdw)
คุณสามารถใช้ table Pragma และสร้างตารางชั่วคราว:
BEGIN
CREATE TEMP TABLE xxx(a int);
PERFORM plpgsql_check_pragma('table: xxx(a int)');
INSERT INTO xxx VALUES(10);
PERFORM plpgsql_check_pragma('table: [pg_temp].zzz(like schemaname.table1 including all)');
...
ฟังก์ชั่น plpgsql_show_dependency_tb จะแสดงฟังก์ชั่นทั้งหมดตัวดำเนินการและความสัมพันธ์ที่ใช้ภายในฟังก์ชั่นที่ผ่านการประมวลผล:
postgres=# select * from plpgsql_show_dependency_tb('testfunc(int,float)');
┌──────────┬───────┬────────┬─────────┬────────────────────────────┐
│ type │ oid │ schema │ name │ params │
╞══════════╪═══════╪════════╪═════════╪════════════════════════════╡
│ FUNCTION │ 36008 │ public │ myfunc1 │ (integer,double precision) │
│ FUNCTION │ 35999 │ public │ myfunc2 │ (integer,double precision) │
│ OPERATOR │ 36007 │ public │ ** │ (integer,integer) │
│ RELATION │ 36005 │ public │ myview │ │
│ RELATION │ 36002 │ public │ mytable │ │
└──────────┴───────┴────────┴─────────┴────────────────────────────┘
(4 rows)
อาร์กิวเมนต์เสริมของ plpgsql_show_dependency_tb เป็น relid , anyelementtype , enumtype , anyrangetype , anycompatibletype และ anycompatiblerangetype
PLPGSQL_CHECK มีโปรไฟล์ง่าย ๆ ของฟังก์ชั่นและขั้นตอนของ PLPGSQL มันสามารถทำงานกับ/ไม่สามารถเข้าถึงหน่วยความจำที่ใช้ร่วมกัน ขึ้นอยู่กับการกำหนดค่า shared_preload_libraries เมื่อ PLPGSQL_CHECK เริ่มต้นโดย shared_preload_libraries จากนั้นจะสามารถจัดสรรหน่วยความจำที่ใช้ร่วมกันและโปรไฟล์ของฟังก์ชั่นจะถูกเก็บไว้ที่นั่น เมื่อ PLPGSQL_CHECK ไม่สามารถจัดสรรหน่วยความจำที่ใช้ร่วมกันได้โปรไฟล์จะถูกเก็บไว้ในหน่วยความจำเซสชัน
เนื่องจากการพึ่งพาอาศัยกัน shared_preload_libraries ควรมี plpgsql ก่อน
postgres=# show shared_preload_libraries ;
┌──────────────────────────┐
│ shared_preload_libraries │
╞══════════════════════════╡
│ plpgsql,plpgsql_check │
└──────────────────────────┘
(1 row)
Profiler จะทำงานเมื่อ GUC plpgsql_check.profiler เปิดอยู่ Profiler ไม่จำเป็นต้องใช้หน่วยความจำที่ใช้ร่วมกัน แต่หากมีหน่วยความจำที่ใช้ร่วมกันไม่เพียงพอ Profiler จะถูก จำกัด เพียงแค่เซสชันที่ใช้งานอยู่ Profiler สามารถเปิดใช้งานได้โดยการเรียกใช้ฟังก์ชั่น plpgsql_check_profiler(true) และปิดการใช้งานโดยเรียกฟังก์ชั่นเดียวกันกับอาร์กิวเมนต์ false (หรือ on ตัวอักษร off )
PLPGSQL_CHECK ควรเริ่มต้นก่อนที่จะดำเนินการฟังก์ชัน PLPGSQL ใด ๆ การเริ่มต้นก่อนกำหนดเท่านั้นทำให้มั่นใจได้ว่าการทำงานที่ถูกต้องของ Profiler และ Tracer เมื่อคุณไม่ได้ใช้ shared_preloaded_libraries คุณสามารถใช้คำสั่ง load 'plpgsql_check' แทน
เมื่อ plpgsql_check เริ่มต้นโดย shared_preload_libraries GUC อื่นจะพร้อมใช้งานเพื่อกำหนดค่าหน่วยความจำที่ใช้ร่วมกันที่ใช้โดย Profiler: plpgsql_check.profiler_max_shared_chunks สิ่งนี้กำหนดจำนวนคำสั่งสูงสุดที่สามารถเก็บไว้ในหน่วยความจำที่ใช้ร่วมกัน สำหรับแต่ละฟังก์ชัน PLPGSQL (หรือขั้นตอน) เนื้อหาทั้งหมดจะถูกแบ่งออกเป็นชิ้นส่วน 30 คำสั่ง หากจำเป็นสามารถใช้ชิ้นหลายชิ้นเพื่อจัดเก็บเนื้อหาทั้งหมดของฟังก์ชั่นเดียว ก้อนเดียวคือ 1704 ไบต์ ค่าเริ่มต้นสำหรับ GUC นี้คือ 15000 ซึ่งน่าจะเพียงพอสำหรับโครงการขนาดใหญ่ที่มีงบหลายแสนใบใน PLPGSQL และจะใช้หน่วยความจำประมาณ 24MB หากโครงการของคุณไม่ต้องการจำนวนชิ้นจำนวนมากคุณสามารถตั้งค่าพารามิเตอร์นี้เป็นจำนวนน้อยกว่าเพื่อลดการใช้หน่วยความจำ ค่าต่ำสุดคือ 50 (ซึ่งควรใช้หน่วยความจำประมาณ 83KB) และค่าสูงสุดคือ 100000 (ซึ่งควรใช้หน่วยความจำประมาณ 163MB) การเปลี่ยนพารามิเตอร์นี้ต้องใช้การรีสตาร์ท PostgreSQL
Profiler จะดึงตัวระบุการสืบค้นสำหรับแต่ละคำสั่งที่มีนิพจน์หรือคำสั่งที่ปรับให้เหมาะสม โปรดทราบว่าสิ่งนี้ต้องใช้ pg_stat_statements หรือส่วนขยายของบุคคลที่สามที่คล้ายกันอื่น ๆ ) ที่จะติดตั้ง มีข้อ จำกัด บางประการในการดึงตัวระบุตัวระบุ:
ความสนใจ: การอัปเดตของโปรไฟล์ที่ใช้ร่วมกันสามารถลดประสิทธิภาพของเซิร์ฟเวอร์ภายใต้โหลดที่สูงขึ้น
โปรไฟล์สามารถแสดงโดยฟังก์ชั่น plpgsql_profiler_function_tb :
postgres=# select lineno, avg_time, source from plpgsql_profiler_function_tb('fx(int)');
┌────────┬──────────┬───────────────────────────────────────────────────────────────────┐
│ lineno │ avg_time │ source │
╞════════╪══════════╪═══════════════════════════════════════════════════════════════════╡
│ 1 │ │ │
│ 2 │ │ declare result int = 0; │
│ 3 │ 0.075 │ begin │
│ 4 │ 0.202 │ for i in 1..$1 loop │
│ 5 │ 0.005 │ select result + i into result; select result + i into result; │
│ 6 │ │ end loop; │
│ 7 │ 0 │ return result; │
│ 8 │ │ end; │
└────────┴──────────┴───────────────────────────────────────────────────────────────────┘
(9 rows)
เวลาในผลลัพธ์อยู่ใน miliseconds
โปรไฟล์ต่อคำสั่ง (ไม่ใช่ต่อบรรทัด) สามารถแสดงโดยฟังก์ชั่น plpgsql_profiler_function_statements_tb:
CREATE OR REPLACE FUNCTION public.fx1(a integer)
RETURNS integer
LANGUAGE plpgsql
1 AS $function$
2 begin
3 if a > 10 then
4 raise notice 'ahoj';
5 return -1;
6 else
7 raise notice 'nazdar';
8 return 1;
9 end if;
10 end;
11 $function$
postgres=# select stmtid, parent_stmtid, parent_note, lineno, exec_stmts, stmtname
from plpgsql_profiler_function_statements_tb('fx1');
┌────────┬───────────────┬─────────────┬────────┬────────────┬─────────────────┐
│ stmtid │ parent_stmtid │ parent_note │ lineno │ exec_stmts │ stmtname │
╞════════╪═══════════════╪═════════════╪════════╪════════════╪═════════════════╡
│ 0 │ ∅ │ ∅ │ 2 │ 0 │ statement block │
│ 1 │ 0 │ body │ 3 │ 0 │ IF │
│ 2 │ 1 │ then body │ 4 │ 0 │ RAISE │
│ 3 │ 1 │ then body │ 5 │ 0 │ RETURN │
│ 4 │ 1 │ else body │ 7 │ 0 │ RAISE │
│ 5 │ 1 │ else body │ 8 │ 0 │ RETURN │
└────────┴───────────────┴─────────────┴────────┴────────────┴─────────────────┘
(6 rows)
โปรไฟล์ที่เก็บไว้ทั้งหมดสามารถแสดงได้โดยการเรียกใช้ฟังก์ชัน plpgsql_profiler_functions_all :
postgres=# select * from plpgsql_profiler_functions_all();
┌───────────────────────┬────────────┬────────────┬──────────┬─────────────┬──────────┬──────────┐
│ funcoid │ exec_count │ total_time │ avg_time │ stddev_time │ min_time │ max_time │
╞═══════════════════════╪════════════╪════════════╪══════════╪═════════════╪══════════╪══════════╡
│ fxx(double precision) │ 1 │ 0.01 │ 0.01 │ 0.00 │ 0.01 │ 0.01 │
└───────────────────────┴────────────┴────────────┴──────────┴─────────────┴──────────┴──────────┘
(1 row)
มีสองฟังก์ชั่นสำหรับการทำความสะอาดโปรไฟล์ที่เก็บไว้: plpgsql_profiler_reset_all() และ plpgsql_profiler_reset(regprocedure)
plpgsql_check มีสองฟังก์ชั่น:
plpgsql_coverage_statements(name)plpgsql_coverage_branches(name)มี PLPGSQL Profiler ที่ดีมากอีกอย่างหนึ่ง - https://github.com/glynastill/plprofiler
ส่วนขยายของฉันได้รับการออกแบบให้ใช้งานง่ายและใช้งานได้ง่าย ไม่มีอะไรมากหรือน้อย
plprofiler มีความซับซ้อนมากขึ้น มันสร้างกราฟการโทรและจากกราฟนี้สามารถสร้างกราฟเปลวไฟของเวลาดำเนินการ
ส่วนขยายทั้งสองสามารถใช้ร่วมกับคุณสมบัติของ Builtin PostgreSQL - ฟังก์ชั่นการติดตาม
set track_functions to 'pl';
...
select * from pg_stat_user_functions;
PLPGSQL_CHECK ให้ความเป็นไปได้ในการติดตาม - ในโหมดนี้คุณสามารถเห็นการแจ้งเตือนในฟังก์ชันเริ่มต้นหรือสิ้นสุด (คำย้ำและคำสั่งเริ่มต้น) และคำสั่งเริ่มต้นหรือสิ้นสุด (verbose verbosity) สำหรับการเริ่มต้นและ verbose verbosity เนื้อหาของอาร์กิวเมนต์ฟังก์ชั่นจะปรากฏขึ้น เนื้อหาของตัวแปรที่เกี่ยวข้องจะปรากฏขึ้นเมื่อคำย้ำเป็น verbose
postgres=# do $$ begin perform fx(10,null, 'now', e'stěhule'); end; $$;
NOTICE: #0 ->> start of inline_code_block (Oid=0)
NOTICE: #2 ->> start of function fx(integer,integer,date,text) (Oid=16405)
NOTICE: #2 call by inline_code_block line 1 at PERFORM
NOTICE: #2 "a" => '10', "b" => null, "c" => '2020-08-03', "d" => 'stěhule'
NOTICE: #4 ->> start of function fx(integer) (Oid=16404)
NOTICE: #4 call by fx(integer,integer,date,text) line 1 at PERFORM
NOTICE: #4 "a" => '10'
NOTICE: #4 <<- end of function fx (elapsed time=0.098 ms)
NOTICE: #2 <<- end of function fx (elapsed time=0.399 ms)
NOTICE: #0 <<- end of block (elapsed time=0.754 ms)
หมายเลขหลังจาก # คือตัวนับเฟรมการดำเนินการ (หมายเลขนี้เกี่ยวข้องกับความลึกของสแต็กบริบทข้อผิดพลาด) ช่วยให้สามารถจับคู่การเริ่มต้นและสิ้นสุดของฟังก์ชั่น
การติดตามถูกเปิดใช้งานโดยการตั้งค่า plpgsql_check.tracer เป็น on ความสนใจ - การเปิดใช้งานพฤติกรรมนี้มีผลกระทบเชิงลบอย่างมีนัยสำคัญต่อประสิทธิภาพ (ไม่เหมือน Profiler) คุณสามารถตั้งค่าระดับสำหรับเอาต์พุตที่ใช้โดย Tracer plpgsql_check.tracer_errlevel (ค่าเริ่มต้นคือ notice ) เนื้อหาเอาท์พุทถูก จำกัด ด้วยความยาวที่ระบุโดย plpgsql_check.tracer_variable_max_length ตัวแปรการกำหนดค่า tracer สามารถเปิดใช้งานได้โดยการเรียกใช้ฟังก์ชัน plpgsql_check_tracer(true) และปิดการใช้งานโดยเรียกฟังก์ชั่นเดียวกันกับอาร์กิวเมนต์ false (หรือ on ตัวอักษร off )
ขั้นแรกการใช้งานของผู้ติดตามควรได้รับการเปิดใช้งานอย่างชัดเจนโดย superuser โดยการตั้งค่า set plpgsql_check.enable_tracer to on; หรือ plpgsql_check.enable_tracer to on ใน postgresql.conf นี่คือการป้องกันความปลอดภัย ตัวติดตามแสดงเนื้อหาของตัวแปรของ PLPGSQL จากนั้นข้อมูลที่ละเอียดอ่อนด้านความปลอดภัยบางอย่างสามารถแสดงต่อผู้ใช้ที่ไม่มีสิทธิ์ (เมื่อเขาทำงานฟังก์ชั่นการรักษาความปลอดภัยที่แน่นอน) ประการที่สองควรโหลดส่วนขยาย plpgsql_check มันสามารถทำได้โดยการดำเนินการของฟังก์ชัน plpgsql_check บางอย่างหรืออย่างชัดเจนโดย load 'plpgsql_check'; - คุณสามารถใช้ตัวเลือกการกำหนดค่าของ shared_preload_libraries , local_preload_libraries หรือ session_preload_libraries
ในโหมด verbose สั้น ๆ เอาต์พุตจะลดลง:
postgres=# set plpgsql_check.tracer_verbosity TO terse;
SET
postgres=# do $$ begin perform fx(10,null, 'now', e'stěhule'); end; $$;
NOTICE: #0 start of inline code block (oid=0)
NOTICE: #2 start of fx (oid=16405)
NOTICE: #4 start of fx (oid=16404)
NOTICE: #4 end of fx
NOTICE: #2 end of fx
NOTICE: #0 end of inline code block
ในโหมด verbose เอาต์พุตจะขยายเกี่ยวกับรายละเอียดคำสั่ง:
postgres=# do $$ begin perform fx(10,null, 'now', e'stěhule'); end; $$;
NOTICE: #0 ->> start of block inline_code_block (oid=0)
NOTICE: #0.1 1 --> start of PERFORM
NOTICE: #2 ->> start of function fx(integer,integer,date,text) (oid=16405)
NOTICE: #2 call by inline_code_block line 1 at PERFORM
NOTICE: #2 "a" => '10', "b" => null, "c" => '2020-08-04', "d" => 'stěhule'
NOTICE: #2.1 1 --> start of PERFORM
NOTICE: #2.1 "a" => '10'
NOTICE: #4 ->> start of function fx(integer) (oid=16404)
NOTICE: #4 call by fx(integer,integer,date,text) line 1 at PERFORM
NOTICE: #4 "a" => '10'
NOTICE: #4.1 6 --> start of assignment
NOTICE: #4.1 "a" => '10', "b" => '20'
NOTICE: #4.1 <-- end of assignment (elapsed time=0.076 ms)
NOTICE: #4.1 "res" => '130'
NOTICE: #4.2 7 --> start of RETURN
NOTICE: #4.2 "res" => '130'
NOTICE: #4.2 <-- end of RETURN (elapsed time=0.054 ms)
NOTICE: #4 <<- end of function fx (elapsed time=0.373 ms)
NOTICE: #2.1 <-- end of PERFORM (elapsed time=0.589 ms)
NOTICE: #2 <<- end of function fx (elapsed time=0.727 ms)
NOTICE: #0.1 <-- end of PERFORM (elapsed time=1.147 ms)
NOTICE: #0 <<- end of block (elapsed time=1.286 ms)
คุณสมบัติพิเศษของ Tracer คือการติดตามคำสั่ง ASSERT เมื่อ plpgsql_check.trace_assert on เมื่อ plpgsql_check.trace_assert_verbosity เป็น DEFAULT ดังนั้นตัวแปรของฟังก์ชั่นหรือโพรซีเดอร์ทั้งหมดจะปรากฏขึ้นเมื่อการยืนยันการแสดงออกเป็นเท็จ เมื่อการกำหนดค่านี้เป็น VERBOSE ตัวแปรทั้งหมดจากเฟรม PLPGSQL ทั้งหมดจะปรากฏขึ้น พฤติกรรมนี้เป็นอิสระจากค่า plpgsql.check_asserts สามารถใช้งานได้แม้ว่าการยืนยันจะถูกปิดใช้งานในรันไทม์ PLPGSQL
postgres=# set plpgsql_check.tracer to off;
postgres=# set plpgsql_check.trace_assert_verbosity TO verbose;
postgres=# do $$ begin perform fx(10,null, 'now', e'stěhule'); end; $$;
NOTICE: #4 PLpgSQL assert expression (false) on line 12 of fx(integer) is false
NOTICE: "a" => '10', "res" => null, "b" => '20'
NOTICE: #2 PL/pgSQL function fx(integer,integer,date,text) line 1 at PERFORM
NOTICE: "a" => '10', "b" => null, "c" => '2020-08-05', "d" => 'stěhule'
NOTICE: #0 PL/pgSQL function inline_code_block line 1 at PERFORM
ERROR: assertion failed
CONTEXT: PL/pgSQL function fx(integer) line 12 at ASSERT
SQL statement "SELECT fx(a)"
PL/pgSQL function fx(integer,integer,date,text) line 1 at PERFORM
SQL statement "SELECT fx(10,null, 'now', e'stěhule')"
PL/pgSQL function inline_code_block line 1 at PERFORM
postgres=# set plpgsql.check_asserts to off;
SET
postgres=# do $$ begin perform fx(10,null, 'now', e'stěhule'); end; $$;
NOTICE: #4 PLpgSQL assert expression (false) on line 12 of fx(integer) is false
NOTICE: "a" => '10', "res" => null, "b" => '20'
NOTICE: #2 PL/pgSQL function fx(integer,integer,date,text) line 1 at PERFORM
NOTICE: "a" => '10', "b" => null, "c" => '2020-08-05', "d" => 'stěhule'
NOTICE: #0 PL/pgSQL function inline_code_block line 1 at PERFORM
DO
Tracer สามารถแสดงการใช้งาน Buffer Buffer ID ( nxids ) หมายเลข tnl ที่แสดงคือหมายเลขระดับการทำรังของธุรกรรม (สำหรับ PLPGSQL มันขึ้นอยู่กับความลึกของบล็อกที่มีตัวจัดการข้อยกเว้น)
เคอร์เซอร์ของ PLPGSQL เป็นเพียงชื่อของเคอร์เซอร์ SQL วงจรชีวิตของเคอร์เซอร์ SQL ไม่ได้เข้าร่วมกับขอบเขตของตัวแปรเคอร์เซอร์ของ PLPGSQL ที่เกี่ยวข้อง เคอร์เซอร์ SQL ถูกปิดบังด้วยตนเองเมื่อจบการทำธุรกรรม แต่สำหรับการทำธุรกรรมที่ยาวนานและเคอร์เซอร์ที่เปิดมากเกินไปมันอาจจะสายเกินไป มันจะดีกว่าที่จะปิดเคอร์เซอร์อย่างชัดเจนเมื่อเคอร์เซอร์ไม่จำเป็น (โดยคำสั่งปิด) หากไม่มีปัญหาหน่วยความจำที่สำคัญเป็นไปได้
เมื่อคำสั่งเปิดพยายามใช้เคอร์เซอร์ที่ยังไม่ปิดการเตือนจะเพิ่มขึ้น คุณสมบัตินี้สามารถปิดใช้งานได้โดยการตั้ง plpgsql_check.cursors_leaks to off การตรวจสอบนี้ไม่ได้ใช้งานเมื่อรูทีนเรียกว่าซ้ำ
สามารถตรวจสอบเคอร์เซอร์ที่ไม่ได้เปิดได้ทันทีเมื่อฟังก์ชั่นเสร็จสิ้น การตรวจสอบนี้ถูกปิดใช้งานโดยค่าเริ่มต้นและควรเปิดใช้งานโดย plpgsql_check.strict_cursors_leaks to on
เคอร์เซอร์ที่ไม่ได้รับการรายงานจะถูกรายงานครั้งเดียว
หากคุณใช้ plugin_debugger (debugger plpgsql) พร้อมกับ plpgsql_check ดังนั้น plpgsql_check ควรเริ่มต้นหลังจาก plugin_debugger (เนื่องจาก plugin_debugger ไม่รองรับการแบ่งปัน API ของ PL/PGSQL) ตัวอย่างเช่น ( postgresql.conf ):
shared_preload_libraries = 'plugin_debugger,plpgsql,plpgsql_check'
Tracer พิมพ์เนื้อหาของตัวแปรหรืออาร์กิวเมนต์ฟังก์ชั่น สำหรับฟังก์ชั่นการรักษาความปลอดภัยเนื้อหานี้สามารถเก็บข้อมูลความปลอดภัยที่ละเอียดอ่อน นี่คือเหตุผลที่ Tracer ถูกปิดใช้งานโดยค่าเริ่มต้นและควรเปิดใช้งานเฉพาะกับสิทธิ์ผู้ใช้ Super plpgsql_check.enable_tracer
คุณสามารถกำหนดค่าพฤติกรรม PLPGSQL_CHECK ภายในฟังก์ชั่นตรวจสอบด้วยฟังก์ชั่น "PRAGMA" นี่คือการเปรียบเทียบภาษา PL/SQL หรือ ADA ของคุณสมบัติ Pragma PLPGSQL ไม่รองรับ Pragma แต่ PLPGSQL_CHECK ตรวจจับฟังก์ชั่นชื่อ plpgsql_check_pragma และใช้ตัวเลือกจากพารามิเตอร์ของฟังก์ชันนี้ ตัวเลือก PLPGSQL_CHECK เหล่านี้ใช้ได้กับตอนท้ายของคำสั่งกลุ่มนี้
CREATE OR REPLACE FUNCTION test()
RETURNS void AS $$
BEGIN
...
-- for following statements disable check
PERFORM plpgsql_check_pragma('disable:check');
...
-- enable check again
PERFORM plpgsql_check_pragma('enable:check');
...
END;
$$ LANGUAGE plpgsql;
ฟังก์ชั่น plpgsql_check_pragma เป็นฟังก์ชั่นที่ไม่เปลี่ยนรูปแบบที่ส่งคืนหนึ่ง มันถูกกำหนดโดยส่วนขยาย plpgsql_check คุณสามารถประกาศฟังก์ชั่น plpgsql_check_pragma ทางเลือกได้เช่น:
CREATE OR REPLACE FUNCTION plpgsql_check_pragma(VARIADIC args[])
RETURNS int AS $$
SELECT 1
$$ LANGUAGE sql IMMUTABLE;
การใช้ฟังก์ชั่น Pragma ในส่วนประกาศของตัวเลือกชุดบล็อกยอดนิยมในระดับฟังก์ชั่นด้วย
CREATE OR REPLACE FUNCTION test()
RETURNS void AS $$
DECLARE
aux int := plpgsql_check_pragma('disable:extra_warnings');
...
ไวยากรณ์ที่สั้นกว่าสำหรับ Pragma ได้รับการสนับสนุนเช่นกัน:
CREATE OR REPLACE FUNCTION test()
RETURNS void AS $$
DECLARE r record;
BEGIN
PERFORM 'PRAGMA:TYPE:r (a int, b int)';
PERFORM 'PRAGMA:TABLE: x (like pg_class)';
...
echo:str - Print String (สำหรับการทดสอบ) ภายในสตริงสามารถใช้ "ตัวแปร": @@ id, @@ name, @@ Signature
status:check status:tracer status:other_warnings status:performance_warnings status:extra_warnings status:security_warnings นี้ส่งออกค่าปัจจุบัน (เช่น Other_warnings เปิดใช้งาน)
enable:check , enable:tracer , enable:other_warnings , enable:performance_warnings , enable:extra_warnings , enable:security_warnings
disable:check , disable:tracer , disable:other_warnings , disable:performance_warnings , disable:extra_warnings , disable:security_warnings สิ่งนี้สามารถใช้เพื่อปิดใช้คำใบ้ในการกลับมาจากฟังก์ชั่นใดก็ได้ เพียงแค่ใส่ pragma ก่อนคำสั่งคืน
type:varname typename หรือ type:varname (fieldname type, ...) - ตั้งค่าประเภทเป็นตัวแปรของประเภทบันทึก
table: name (column_name type, ...) หรือ table: name (like tablename) - สร้างตารางชั่วคราวชั่วคราว (หากคุณต้องการระบุ schema จากนั้นอนุญาตเฉพาะ schema pg_temp เท่านั้น
sequence: name - สร้างลำดับชั่วคราวชั่วคราว
assert-schema: varname - การยืนยันเวลาตรวจสอบ - ตรวจสอบให้แน่ใจว่าสคีมาที่ระบุโดยตัวแปรนั้นถูกต้อง
assert-table: [ varname_schema, ] , varname - ตรวจสอบให้แน่ใจว่าชื่อตารางที่ระบุโดยตัวแปร (โดยการติดตามคงที่) จะถูกต้อง
assert-column: [varname_schema, ], varname_table , varname - ตรวจสอบคอลัมน์ so Spefified โดยตัวแปรนั้นถูกต้อง
Pragmas enable:tracer และ disable:tracer ทำงานอยู่สำหรับ postgres 12 และสูงกว่า
PLPGSQL_CHECK ไม่รองรับการอัปเดต (ของ PLPGSQL_CHECK) คุณควรวางสิ่งนี้ก่อนที่จะติดตั้งเวอร์ชันใหม่ของส่วนขยายนี้
คุณต้องมีสภาพแวดล้อมการพัฒนาสำหรับส่วนขยาย PostgreSQL:
make clean
make install
ผลลัพธ์:
[pavel@localhost plpgsql_check]$ make USE_PGXS=1 clean
rm -f plpgsql_check.so libplpgsql_check.a libplpgsql_check.pc
rm -f plpgsql_check.o
rm -rf results/ regression.diffs regression.out tmp_check/ log/
[pavel@localhost plpgsql_check]$ make USE_PGXS=1 all
clang -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I/usr/local/pgsql/lib/pgxs/src/makefiles/../../src/pl/plpgsql/src -I. -I./ -I/usr/local/pgsql/include/server -I/usr/local/pgsql/include/internal -D_GNU_SOURCE -c -o plpgsql_check.o plpgsql_check.c
clang -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I/usr/local/pgsql/lib/pgxs/src/makefiles/../../src/pl/plpgsql/src -shared -o plpgsql_check.so plpgsql_check.o -L/usr/local/pgsql/lib -Wl,--as-needed -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags
[pavel@localhost plpgsql_check]$ su root
Password: *******
[root@localhost plpgsql_check]# make USE_PGXS=1 install
/usr/bin/mkdir -p '/usr/local/pgsql/lib'
/usr/bin/mkdir -p '/usr/local/pgsql/share/extension'
/usr/bin/mkdir -p '/usr/local/pgsql/share/extension'
/usr/bin/install -c -m 755 plpgsql_check.so '/usr/local/pgsql/lib/plpgsql_check.so'
/usr/bin/install -c -m 644 plpgsql_check.control '/usr/local/pgsql/share/extension/'
/usr/bin/install -c -m 644 plpgsql_check--0.9.sql '/usr/local/pgsql/share/extension/'
[root@localhost plpgsql_check]# exit
[pavel@localhost plpgsql_check]$ make USE_PGXS=1 installcheck
/usr/local/pgsql/lib/pgxs/src/makefiles/../../src/test/regress/pg_regress --inputdir=./ --psqldir='/usr/local/pgsql/bin' --dbname=pl_regression --load-language=plpgsql --dbname=contrib_regression plpgsql_check_passive plpgsql_check_active plpgsql_check_active-9.5
(using postmaster on Unix socket, default port)
============== dropping database "contrib_regression" ==============
DROP DATABASE
============== creating database "contrib_regression" ==============
CREATE DATABASE
ALTER DATABASE
============== installing plpgsql ==============
CREATE LANGUAGE
============== running regression test queries ==============
test plpgsql_check_passive ... ok
test plpgsql_check_active ... ok
test plpgsql_check_active-9.5 ... ok
=====================
All 3 tests passed.
=====================
บางครั้งการรวบรวมที่ประสบความสำเร็จอาจต้องใช้แพ็คเกจ libicu -dev (PostgreSQL 10 และสูงกว่า - เมื่อ PG ถูกรวบรวมด้วยการสนับสนุน ICU)
sudo apt install libicu-dev
คุณสามารถตรวจสอบไลบรารี DLL ที่คอมไพล์ preompiled http://okbob.blogspot.cz/2015/02/plpgsqlcheck-is-available-for-microsoft.html, http://okbob.blogspot.com/2023/10/Compiled-dlll-DmlC
หรือรวบรวมโดยตัวเอง:
plpgsql_check.dll ไปที่ PostgreSQL14libplpgsql_check.control และ plpgsql_check--2.1.sql เพื่อ PostgreSQL14shareextension meson setup buildcd buildninjasudo ninja installการรวบรวมกับ PostgreSQL 10 ต้องใช้ libicu!
ลิขสิทธิ์ (c) Pavel Stehule ([email protected])
ได้รับอนุญาตโดยไม่ต้องเสียค่าใช้จ่ายสำหรับบุคคลใด ๆ ที่ได้รับสำเนาซอฟต์แวร์นี้และไฟล์เอกสารที่เกี่ยวข้อง ("ซอฟต์แวร์") เพื่อจัดการในซอฟต์แวร์โดยไม่มีการ จำกัด รวมถึง แต่ไม่ จำกัด เฉพาะสิทธิ์ในการใช้สำเนาดัดแปลงผสานเผยแพร่เผยแพร่
ประกาศลิขสิทธิ์ข้างต้นและประกาศการอนุญาตนี้จะรวมอยู่ในสำเนาทั้งหมดหรือส่วนสำคัญของซอฟต์แวร์
ซอฟต์แวร์มีให้ "ตามสภาพ" โดยไม่มีการรับประกันใด ๆ ไม่ว่าโดยชัดแจ้งหรือโดยนัยรวมถึง แต่ไม่ จำกัด เฉพาะการรับประกันความสามารถในการค้าการออกกำลังกายสำหรับวัตถุประสงค์เฉพาะและการไม่เข้าร่วม ไม่ว่าในกรณีใดผู้เขียนหรือผู้ถือลิขสิทธิ์จะต้องรับผิดชอบต่อการเรียกร้องความเสียหายหรือความรับผิดอื่น ๆ ไม่ว่าจะเป็นการกระทำของสัญญาการละเมิดหรืออื่น ๆ ที่เกิดขึ้นจากหรือเกี่ยวข้องกับซอฟต์แวร์หรือการใช้งานหรือการติดต่ออื่น ๆ ในซอฟต์แวร์
ถ้าคุณชอบส่งโปสการ์ดไปที่ที่อยู่
Pavel Stehule
Skalice 12
256 01 Benesov u Prahy
Czech Republic
ฉันเชิญคำถามความคิดเห็นรายงานข้อผิดพลาดแพตช์บนที่อยู่อีเมล [email protected]