Phiên bản được hỗ trợ:hiện tại(17)16 / 15 / 14 / 13
Phiên bản phát triển:18 / Devel
Phiên bản không được hỗ trợ:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1
Tài liệu này dành cho phiên bản không được hỗ trợ của PostgreSQL.
Bạn có thể muốn xem cùng kèo bóng đá c1 trang chohiện tạiPhiên bản hoặc một trong kèo bóng đá c1 phiên bản được hỗ trợ khác được liệt kê ở trên thay thế.

36.10. kèo bóng đá c1 hàm ngôn ngữ C#

kèo bóng đá c1 hàm do người dùng xác định có thể được viết bằng C (hoặc một ngôn ngữ có thể được thực hiện tương thích với C, chẳng hạn như C ++). kèo bóng đá c1 chức năng như vậy được biên dịch thành kèo bóng đá c1 đối tượng có thể tải động (còn được gọi là thư viện được chia sẻ) và được tải bởi máy chủ theo yêu cầu.HồiC Ngôn ngữkèo bóng đá c1 chức năng từNội bộHàm - kèo bóng đá c1 quy ước mã hóa thực tế về cơ bản giống nhau cho cả hai. .

Hiện tại chỉ có một quy ước gọi được sử dụng cho kèo bóng đá c1 hàm C (HồiPhiên bản 1). Hỗ trợ cho quy ước gọi đó được biểu thị bằng cách viết kèo bóng đá c1pg_function_info_v1 ()cuộc gọi macro cho chức năng, như được minh họa bên dưới.

36.10.1. Tải động#

Lần đầu tiên một kèo bóng đá c1 do người dùng xác định trong một tệp đối tượng có thể tải cụ thể được gọi trong phiên, trình tải động tải tệp đối tượng đó vào bộ nhớ để có thể gọi kèo bóng đá c1. TheTạo chức năngĐối với chức năng C do người dùng xác định phải chỉ định hai phần thông tin cho kèo bóng đá c1: tên của tệp đối tượng có thể tải và tên C (ký hiệu liên kết) của kèo bóng đá c1 cụ thể để gọi trong tệp đối tượng đó. Nếu tên C không được chỉ định rõ ràng thì nó được coi là giống như tên kèo bóng đá c1 SQL.

Thuật toán sau được sử dụng để định vị tệp đối tượng được chia sẻ dựa trên tên được đưa ra trongTạo chức nănglệnh:

  1. Nếu tên là đường dẫn tuyệt đối, tệp đã cho được tải.

  2. Nếu tên bắt đầu bằng chuỗi$ libdir, phần đó được thay thế bằngPostgreSQLTên thư mục thư viện gói, được xác định tại thời điểm xây dựng.

  3. Nếu tên không chứa phần thư mục, tệp được tìm kiếm trong đường dẫn được chỉ định bởi biến cấu hìnhDynamic_l Library_path.

  4. Nếu không (tệp không được tìm thấy trong đường dẫn hoặc nó chứa kèo bóng đá c1 phần thư mục không Absolute), trình tải động sẽ cố gắng lấy tên như đã đưa ra, rất có thể sẽ thất bại. (Không đáng tin cậy khi phụ thuộc vào thư mục làm việc hiện tại.)

Nếu chuỗi này không hoạt động, phần mở rộng tên tệp thư viện chia sẻ dành riêng cho nền tảng (thường là.so) được thêm vào tên đã cho và chuỗi này được thử lại. Nếu điều đó cũng thất bại, tải sẽ không thành công.

Nên định vị kèo bóng đá c1 thư viện được chia sẻ liên quan đến$ libdirhoặc thông qua đường dẫn thư viện động. Điều này đơn giản hóa phiên bản nâng cấp nếu cài đặt mới ở kèo bóng đá c1 vị trí khác.$ libdirViết tắt có thể được tìm thấy với lệnhpg_config - -pkglibdir.

ID người dùngPostgreSQLMáy chủ chạy vì phải có thể đi qua đường dẫn đến tệp bạn định tải. Làm cho tệp hoặc kèo bóng đá c1 thư mục cấp cao hơn không thể đọc được và/hoặc không thể thực thi bởiPostgresNgười dùng là kèo bóng đá c1 sai lầm phổ biến.

Trong mọi trường hợp, tên tệp được đưa ra trongTạo chức năngLệnh được ghi lại theo nghĩa đen trong kèo bóng đá c1 danh mục hệ thống, vì vậy nếu tệp cần được tải lại, quy trình tương tự được áp dụng.

Lưu ý

PostgreSQLsẽ không tự động biên dịch chức năng C. Tệp đối tượng phải được biên dịch trước khi nó được tham chiếu trongTạo chức nănglệnh. Nhìn thấyPhần 36.10.5Để biết thêm thông tin.

Để đảm bảo rằng kèo bóng đá c1 tệp đối tượng được tải động không được tải vào kèo bóng đá c1 máy chủ không tương thích,POSTGRESQLKiểm tra xem tệp có chứaKhối ma thuậtHồiVới kèo bóng đá c1 nội dung thích hợp. Điều này cho phép máy chủ phát hiện sự không tương thích rõ ràng, chẳng hạn như mã được biên dịch cho một phiên bản chính khác củaPostgreSQL. Để bao gồm một khối ma thuật, hãy viết nó vào một (và chỉ một) của kèo bóng đá c1 tệp nguồn mô -đun, sau khi bao gồm tiêu đềfmgr.h:

pg_module_magic;

hoặc

PG_MODULE_MAGIC_EXT (tham số);

ThePG_MODULE_MAGIC_EXTBiến thể cho phép đặc tả thông tin bổ sung về mô -đun; Hiện tại, kèo bóng đá c1 tên và/hoặc kèo bóng đá c1 chuỗi phiên bản có thể được thêm vào.

PG_MODULE_MAGIC_EXT (

Sau đó, tên và phiên bản có thể được kiểm tra quaPG_GET_LOADED_MODULES ()kèo bóng đá c1. Ý nghĩa của chuỗi phiên bản không bị hạn chế bởiPostgreSQL, nhưng sử dụng kèo bóng đá c1 quy tắc phiên bản ngữ nghĩa được khuyến nghị.

Sau khi nó được sử dụng lần đầu tiên, một tệp đối tượng được tải động được giữ lại trong bộ nhớ. kèo bóng đá c1 cuộc gọi trong tương lai trong cùng một phiên đến (kèo bóng đá c1) hàm trong tệp đó sẽ chỉ phải chịu chi phí nhỏ của tra cứu bảng ký hiệu.

Tùy chọn, một tệp được tải động có thể chứa chức năng khởi tạo. Nếu tệp bao gồm một kèo bóng đá c1 có tên_pg_init, kèo bóng đá c1 đó sẽ được gọi ngay sau khi tải tệp. kèo bóng đá c1 không nhận được thông số và nên trả lại void.

36.10.2. kèo bóng đá c1 loại cơ sở trong kèo bóng đá c1 hàm ngôn ngữ c#

Để biết cách viết kèo bóng đá c1 chức năng ngôn ngữ C, bạn cần biết làm thế nàoPostgreSQLNội bộ thể hiện kèo bóng đá c1 loại dữ liệu cơ sở và cách chúng có thể được truyền đến và từ kèo bóng đá c1 chức năng. Trong nội bộ,PostgreSQLTrân trọng loại cơ sở làBlob of MemoryHàng. kèo bóng đá c1 chức năng do người dùng xác định mà bạn xác định qua một loại lần lượt xác định cáchPostgreSQLCó thể hoạt động trên nó. Đó là,PostgreSQLSẽ chỉ lưu trữ và truy xuất dữ liệu từ đĩa và sử dụng kèo bóng đá c1 chức năng do người dùng xác định của bạn vào đầu vào, xử lý và xuất dữ liệu.

kèo bóng đá c1 loại cơ sở có thể có một trong ba định dạng nội bộ:

  • Truyền theo giá trị, độ dài cố định

  • Pass by tham chiếu, độ dài cố định

  • Pass by tham chiếu, độ dài biến

kèo bóng đá c1 loại giá trị chỉ có thể là 1, 2 hoặc 4 byte theo chiều dài (cũng là 8 byte, nếusizeof (mốc dữ liệu)là 8 trên máy của bạn). Bạn nên cẩn thận để xác định kèo bóng đá c1 loại của bạn sao cho chúng sẽ có cùng kích thước (tính bằng byte) trên tất cả kèo bóng đá c1 kiến ​​trúc.LongLoại nguy hiểm vì nó là 4 byte trên một số máy và 8 byte trên kèo bóng đá c1 máy khác, trong khiintLoại là 4 byte trên hầu hết kèo bóng đá c1 máy Unix. Một triển khai hợp lý củaINT4gõ trên máy Unix có thể là:

/ * 4 byte số nguyên, được truyền theo giá trị */

(Mã PostgreSQL C thực tế gọi loại nàyINT32, bởi vì đó là kèo bóng đá c1 quy ước trong c màintXXcó nghĩa làXX bit. Do đó, lưu ý rằng loại cINT8có kích thước 1 byte. Loại SQLINT8được gọi làINT64Trong C. Xem thêmBảng 36.2.)

Mặt khác, kèo bóng đá c1 loại có độ dài cố định có thể được truyền theo tham chiếu. Ví dụ: đây là việc triển khai mẫu củaPOSTGRESQLloại:

/ * Cấu trúc 16 byte, được truyền qua tham chiếu */

Chỉ có thể sử dụng kèo bóng đá c1 con trỏ như vậy khi chuyển chúng vào và ra khỏiPostgreSQLchức năng. Để trả về giá trị của kèo bóng đá c1 loại như vậy, hãy phân bổ đúng lượng bộ nhớ vớiPalloC, điền vào bộ nhớ được phân bổ và trả lại kèo bóng đá c1 con trỏ cho nó. .PalloCVà chỉ cần trả con trỏ về giá trị đầu vào.)

Cuối cùng, tất cả kèo bóng đá c1 loại có độ dài thay đổi cũng phải được truyền bằng tham chiếu. Tất cả kèo bóng đá c1 loại có độ dài thay đổi phải bắt đầu bằng trường chiều dài mờ có chính xác 4 byte, sẽ được đặt bởiset_varsize; Không bao giờ đặt trường này trực tiếp!

Một điểm quan trọng khác là tránh để lại bất kỳ bit không chính thức nào trong kèo bóng đá c1 giá trị kiểu dữ liệu; Ví dụ, hãy cẩn thận với bất kỳ byte đệm căn chỉnh nào có thể có trong kèo bóng đá c1 cấu trúc.

Cảnh báo

không bao giờSửa đổi nội dung của giá trị đầu vào ngang qua. Nếu bạn làm như vậy, bạn có khả năng tham nhũng dữ liệu trên đĩa, vì con trỏ bạn được cung cấp có thể chỉ trực tiếp vào bộ đệm đĩa.Phần 36.12.

Ví dụ, chúng ta có thể xác định loạiTextnhư sau:

Typedef Struct

The25619_25644Ký hiệu có nghĩa là độ dài thực tế của phần dữ liệu không được chỉ định bởi Tuyên bố này.

Khi thao tác kèo bóng đá c1 loại có độ dài biến, chúng ta phải cẩn thận để phân bổ số lượng bộ nhớ chính xác và đặt trường độ dài một cách chính xác. Ví dụ: nếu chúng tôi muốn lưu trữ 40 byte trongTextCấu trúc, chúng ta có thể sử dụng kèo bóng đá c1 đoạn mã như thế này:

#include "Postgres.h"

Varhdrszgiống nhưsizeof (int32), nhưng nó được coi là phong cách tốt để sử dụng macroVarhdrszđể chỉ kích thước của chi phí cho kèo bóng đá c1 loại có độ dài thay đổi. Ngoài ra, trường chiều dàiphảiđược đặt bằngset_varsizeMacro, không phải bằng cách gán đơn giản.

Bảng 36.2Hiển thị kèo bóng đá c1 loại C tương ứng với nhiều loại dữ liệu SQL tích hợp củaPostgreSQL. Theđược xác định trongCột cung cấp tệp tiêu đề cần được đưa vào để có được định nghĩa loại. .Postgres.hĐầu tiên trong bất kỳ tệp nguồn nào của mã máy chủ, vì nó tuyên bố một số điều mà bạn sẽ cần và vì bao gồm kèo bóng đá c1 tiêu đề khác trước tiên có thể gây ra kèo bóng đá c1 vấn đề về tính di động.

Bảng 36.2. kèo bóng đá c1 loại C tương đương cho kèo bóng đá c1 loại SQL tích hợp

SQL Loại C Loại được xác định trong
Boolean bool Postgres.h(có thể trình biên dịch tích hợp)
Box Box* UTILS/GEO_DECLS.H
bytea bytea* Postgres.h
"Char" char (trình biên dịch tích hợp)
ký tự bpchar* Postgres.h
CID CommandID Postgres.h
ngày dateadt Utils/date.h
float4(Real) float4 Postgres.h
float8(độ chính xác gấp đôi) float8 Postgres.h
INT2(SmallInt) INT16 Postgres.h
INT4(Số nguyên) INT32 Postgres.h
INT8(Bigint) INT64 Postgres.h
Khoảng Khoảng* DataType/Timestamp.h
LSEG LSEG* UTILS/GEO_DECLS.H
tên tên Postgres.h
Số Số Utils/Numeric.h
OID OID Postgres.h
oidvector oidvector* Postgres.h
đường dẫn đường dẫn* UTILS/GEO_DECLS.H
điểm điểm* UTILS/GEO_DECLS.H
RegProc RegProcedure Postgres.h
Text Text* Postgres.h
TID itemPulum Storage/itemptr.h
Thời gian Timeadt Utils/date.h
Thời gian với múi giờ Timetzadt Utils/date.h
Timestamp Timestamp DataType/Timestamp.h
dấu thời gian với múi giờ TIMESTAMPTZ DataType/Timestamp.h
Varchar Varchar* Postgres.h
XID TranstercentID Postgres.h

Bây giờ chúng tôi đã vượt qua tất cả kèo bóng đá c1 cấu trúc có thể có cho kèo bóng đá c1 loại cơ sở, chúng tôi có thể hiển thị một số ví dụ về kèo bóng đá c1 chức năng thực.

36.10.3. Phiên bản 1 Gọi quy ước#

quy ước gọi phiên bản-1 dựa trên kèo bóng đá c1 macro để đàn áp hầu hết sự phức tạp của kèo bóng đá c1 đối số và kết quả truyền. Tuyên bố C của hàm phiên bản-1 luôn luôn:

Datum funcname (pg_function_args)

Ngoài ra, cuộc gọi macro:

pg_function_info_v1 (funcname);

phải xuất hiện trong cùng kèo bóng đá c1 tệp nguồn. (Thông thường, nó được viết ngay trước chính chức năng.) Cuộc gọi macro này không cần thiết choNội bộ-L lý thuyết, kể từPOSTGRESQLGiả sử rằng tất cả kèo bóng đá c1 chức năng nội bộ đều sử dụng quy ước phiên bản 1. Tuy nhiên, nó được yêu cầu cho kèo bóng đá c1 chức năng được tải động.

Trong kèo bóng đá c1 phiên bản-1, mỗi đối số thực tế được tìm nạp bằng cách sử dụngpg_getarg_xxx()Macro tương ứng với kiểu dữ liệu của đối số. .pg_argisnull (); xem bên dưới.) Kết quả được trả về bằngpg_return_xxx()Macro cho loại trả về.pg_getarg_xxx()lấy đối số của nó Số lượng đối số kèo bóng đá c1 để tìm nạp, trong đó số lượng bắt đầu ở 0.pg_return_xxx()lấy đối số của nó giá trị thực tế để trả về.

Để gọi chức năng phiên bản-1 khác, bạn có thể sử dụngDirectFunctionCalln(func, arg1, ..., argn). Điều này đặc biệt hữu ích khi bạn muốn gọi kèo bóng đá c1 chức năng được xác định trong thư viện nội bộ tiêu chuẩn, bằng cách sử dụng giao diện tương tự như chữ ký SQL của chúng.

Những chức năng tiện lợi này và kèo bóng đá c1 chức năng tương tự có thể được tìm thấy trongfmgr.h. TheDirectFunctionCallnGia đình mong đợi một tên kèo bóng đá c1 C là đối số đầu tiên của họ. Cũng cóoidfunctionCallnlấy OID của hàm đích và một số biến thể khác. Tất cả những điều này mong đợi kèo bóng đá c1 đối số của chức năng được cung cấp làDatumS, và tương tự họ trở lạiDatum. Lưu ý rằng cả đối số và kết quả đều không được phép vô hiệu hóa khi sử dụng kèo bóng đá c1 hàm tiện lợi này.

Ví dụ: để gọistarts_with (văn bản, văn bản)kèo bóng đá c1 từ C, bạn có thể tìm kiếm thông qua danh mục và tìm hiểu rằng triển khai C của nó làDatum text_starts_with (pg_function_args)kèo bóng đá c1. Thông thường bạn sẽ sử dụngDirectFunctionCall2 (text_starts_with, ...)để gọi một kèo bóng đá c1 như vậy. Tuy nhiên,starts_with (văn bản, văn bản)Yêu cầu thông tin đối chiếu, vì vậy nó sẽ thất bại vớiKhông thể xác định đối chiếu nào sẽ sử dụng để so sánh chuỗiNếu được gọi theo cách đó. Thay vào đó bạn phải sử dụngDirectFunctionCall2Coll (text_starts_with, ...)và cung cấp sự đối chiếu mong muốn, thường được chuyển qua từpg_get_collation (), như được hiển thị trong ví dụ dưới đây.

fmgr.hCũng cung cấp kèo bóng đá c1 macro tạo điều kiện chuyển đổi giữa kèo bóng đá c1 loại C vàDatum. Ví dụ để biếnDatumthànhText*, bạn có thể sử dụngDatumGetTextpp (x). Trong khi kèo bóng đá c1 số loại có macro có tên nhưTypeGetDatum (x)Để chuyển đổi ngược,Text*không; nó đủ để sử dụng macro chungPolintergetDatum (x)cho điều đó. Nếu tiện ích mở rộng của bạn xác định kèo bóng đá c1 loại bổ sung, thì cũng thường thuận tiện để xác định kèo bóng đá c1 macro tương tự cho kèo bóng đá c1 loại của bạn.

Dưới đây là kèo bóng đá c1 số ví dụ sử dụng quy ước gọi phiên bản-1:

#include "Postgres.h"

Giả sử rằng mã trên đã được chuẩn bị trong tệpfuncs.cvà biên dịch thành một đối tượng được chia sẻ, chúng ta có thể xác định kèo bóng đá c1 chức năng thànhPostgreSQLVới kèo bóng đá c1 lệnh như thế này:

tạo kèo bóng đá c1 add_one (số nguyên) trả về số nguyênThư mục/funcs ',' add_one 'Thư mục/funcs ',' add_one_float8 'Thư mục/funcs ',' makepoint 'Thư mục/funcs ',' copytext 'Thư mục/funcs ',' concat_text 'Thư mục/funcs ',' t_starts_with '

ở đây,Thư mụclà viết tắt của thư mục của tệp thư viện được chia sẻ (ví dụPOSTGRESQLThư mục hướng dẫn, chứa mã cho kèo bóng đá c1 ví dụ được sử dụng trong phần này). (Phong cách tốt hơn sẽ là sử dụng chỉ'funcs'trongASmệnh đề, sau khi đã thêmThư mụcđến đường dẫn tìm kiếm. Trong mọi trường hợp, chúng tôi có thể bỏ qua tiện ích mở rộng dành riêng cho hệ thống cho thư viện được chia sẻ, thường là.so.)

Lưu ý rằng chúng tôi đã chỉ định kèo bóng đá c1 chức năng lànghiêm ngặtHàng, có nghĩa là hệ thống sẽ tự động giả định kết quả null nếu bất kỳ giá trị đầu vào nào là null. Bằng cách này, chúng tôi tránh phải kiểm tra kèo bóng đá c1 đầu vào null trong mã chức năng.pg_argisnull ().

Macropg_argisnull (n)Cho phép một hàm kiểm tra xem mỗi đầu vào có phải là null hay không. (Tất nhiên, làm điều này chỉ cần thiết trong kèo bóng đá c1 chức năng không được khai báonghiêm ngặtKhăn.) Như vớipg_getarg_xxx()macro, kèo bóng đá c1 đối số đầu vào được tính bắt đầu ở mức 0. Lưu ý rằng người ta nên không thực thipg_getarg_xxx()Cho đến khi người ta xác minh rằng đối số không phải là null. Để trả về kết quả null, thực thipg_return_null (); Điều này hoạt động trong cả hai chức năng nghiêm ngặt và không thành công.

Thoạt nhìn, kèo bóng đá c1 quy ước mã hóa phiên bản-1 có thể chỉ là chủ nghĩa tối nghĩa vô nghĩa, so với sử dụng đơn giảnCGọi quy ước. Tuy nhiên, họ cho phép chúng tôi đối phó vớinullcó thể đối số/giá trị trả về vàTOASTED(nén hoặc ra khỏi dòng) giá trị.

kèo bóng đá c1 tùy chọn khác được cung cấp bởi giao diện phiên bản-1 là hai biến thể củapg_getarg_xxx()Macros. Cái đầu tiên trong số này,pg_getarg_xxx_copy (), Đảm bảo trả về kèo bóng đá c1 bản sao của đối số được chỉ định an toàn khi viết vào. .pg_getarg_xxx_copy ()macro đảm bảo kết quả có thể ghi.) Biến thể thứ hai bao gồmpg_getarg_xxx_slice ()Macro có ba đối số. Đầu tiên là số lượng đối số kèo bóng đá c1 (như trên).Bên ngoàiKhăn. (Loại lưu trữ của kèo bóng đá c1 cột có thể được chỉ định bằng cách sử dụngBẢNG ALTERTableNameCột thay đổicolnameĐặt lưu trữStorAgetype. StorAgetypelà kèo bóng đá c1 trongtrơn, bên ngoài, mở rộnghoặcchính.)

Cuối cùng, kèo bóng đá c1 quy ước gọi chức năng phiên bản-1 có thể trả về kết quả tập hợp (Phần 36.10.9) và thực hiện kèo bóng đá c1 chức năng kích hoạt (Chương 37) và Trình xử lý cuộc gọi bằng ngôn ngữ thủ tục (Chương 57). Để biết thêm chi tiết, xemsrc/backend/utils/fmgr/readmeTrong phân phối nguồn.

36.10.4. Viết mã#

Trước khi chúng ta chuyển sang kèo bóng đá c1 chủ đề nâng cao hơn, chúng ta nên thảo luận về một số quy tắc mã hóa choPostgreSQLHàm ngôn ngữ c. Mặc dù có thể tải kèo bóng đá c1 hàm được viết bằng kèo bóng đá c1 ngôn ngữ khác với C thànhPostgreSQL, Điều này thường khó khăn (khi có thể) bởi vì kèo bóng đá c1 ngôn ngữ khác, chẳng hạn như C ++, Fortran hoặc Pascal thường không tuân theo quy ước gọi giống như C. đó là kèo bóng đá c1 ngôn ngữ khác không truyền đối số và trả về kèo bóng đá c1 giá trị giữa kèo bóng đá c1 hàm theo cùng một cách. Vì lý do này, chúng tôi sẽ cho rằng kèo bóng đá c1 hàm ngôn ngữ C của bạn thực sự được viết bằng C.

kèo bóng đá c1 quy tắc cơ bản để viết và xây dựng kèo bóng đá c1 hàm C như sau:

  • Sử dụngpg_config--includedir-serverĐể tìm ra nơiPOSTGRESQLkèo bóng đá c1 tệp tiêu đề máy chủ được cài đặt trên hệ thống của bạn (hoặc hệ thống mà người dùng của bạn sẽ chạy).

  • biên dịch và liên kết mã của bạn để nó có thể được tải động vàoPostgreSQLLuôn yêu cầu cờ đặc biệt. Nhìn thấyPhần 36.10.5Để giải thích chi tiết về cách thực hiện cho hệ điều hành cụ thể của bạn.

  • Hãy nhớ xác định AHồiKhối ma thuậtxôngĐối với thư viện chia sẻ của bạn, như được mô tả trongPhần 36.10.1.

  • Khi phân bổ bộ nhớ, hãy sử dụngPostgreSQLChức năngPalloCPFREEThay vì kèo bóng đá c1 chức năng thư viện C tương ứngmallocmiễn phí. Bộ nhớ được phân bổ bởiPalloCsẽ tự động được giải phóng vào cuối mỗi giao dịch, ngăn chặn rò rỉ bộ nhớ.

  • Luôn bằng không kèo bóng đá c1 byte của cấu trúc của bạn bằng cách sử dụngMemset(hoặc phân bổ chúng bằngPalloC0Ở nơi đầu tiên). Ngay cả khi bạn gán cho từng trường cấu trúc của bạn, có thể có phần đệm căn chỉnh (kèo bóng đá c1 lỗ trong cấu trúc) có chứa kèo bóng đá c1 giá trị rác.

  • Hầu hết kèo bóng đá c1 bên trongPOSTGRESQLkèo bóng đá c1 loại được khai báo trongPostgres.h, trong khi giao diện trình quản lý chức năng (PG_FUNCTION_ARGS, v.v.)fmgr.h, vì vậy bạn sẽ cần bao gồm ít nhất hai tệp này. Vì lý do tính di động, tốt nhất là bao gồmPostgres.h Đầu tiên, trước bất kỳ tệp tiêu đề hệ thống hoặc người dùng nào khác. Bao gồmPostgres.hcũng sẽ bao gồmelog.hpalloc.hcho bạn.

  • Tên biểu tượng được xác định trong kèo bóng đá c1 tệp đối tượng không được xung đột với nhau hoặc với kèo bóng đá c1 ký hiệu được xác định trongPOSTGRESQLCó thể thực thi máy chủ. Bạn sẽ phải đổi tên kèo bóng đá c1 chức năng hoặc biến của mình nếu bạn nhận được thông báo lỗi thành hiệu ứng này.

36.10.5. Biên dịch và liên kết kèo bóng đá c1 chức năng được tải động#

Trước khi bạn có thể sử dụngPostgreSQLkèo bóng đá c1 chức năng mở rộng được viết bằng C, chúng phải được biên dịch và liên kết theo cách đặc biệt để tạo một tệp có thể được máy chủ tải động. Để chính xác, AThư viện chia sẻcần được tạo.

Để biết thông tin ngoài những gì có trong phần này, bạn nên đọc tài liệu của hệ điều hành của mình, đặc biệt là kèo bóng đá c1 trang thủ công cho trình biên dịch C,CCvà Trình chỉnh sửa liên kết,LD. Ngoài ra,POSTGRESQLMã nguồn chứa kèo bóng đá c1 số ví dụ làm việc trongĐóng gópThư mục. Nếu bạn dựa vào kèo bóng đá c1 ví dụ này, bạn sẽ làm cho kèo bóng đá c1 mô -đun của mình phụ thuộc vào tính khả dụng củaPOSTGRESQLTuy nhiên, mã nguồn.

Tạo thư viện chia sẻ thường tương tự như liên kết kèo bóng đá c1 tệp thực thi: Đầu tiên kèo bóng đá c1 tệp nguồn được biên dịch thành kèo bóng đá c1 tệp đối tượng, sau đó kèo bóng đá c1 tệp đối tượng được liên kết với nhau. kèo bóng đá c1 tệp đối tượng cần được tạo dưới dạngMã độc lập vị trí(pic),Điều này có nghĩa là chúng có thể được đặt tại kèo bóng đá c1 vị trí tùy ý trong bộ nhớ khi chúng được thực thi. .

Trong kèo bóng đá c1 ví dụ sau, chúng tôi cho rằng mã nguồn của bạn nằm trong một tệpfoo.cVà chúng tôi sẽ tạo kèo bóng đá c1 thư viện được chia sẻfoo.so. Tệp đối tượng trung gian sẽ được gọi làfoo.otrừ khi có ghi chú khác. Thư viện được chia sẻ có thể chứa nhiều hơn kèo bóng đá c1 tệp đối tượng, nhưng chúng tôi chỉ sử dụng kèo bóng đá c1 tệp ở đây.

FreeBSD

Cờ trình biên dịch để tạopic-FPIC. Để tạo thư viện được chia sẻ, cờ trình biên dịch là-shared.

cc -fpic -c foo.c

Điều này được áp dụng kể từ phiên bản 13.0 củaFreeBSD, kèo bóng đá c1 phiên bản cũ hơn đã sử dụngGCCtrình biên dịch.

Linux

Cờ trình biên dịch để tạopic-FPIC. Cờ trình biên dịch để tạo thư viện chia sẻ là-shared. kèo bóng đá c1 ví dụ hoàn chỉnh trông như thế này:

cc -fpic -c foo.c
MacOS

Đây là một ví dụ. Nó giả định kèo bóng đá c1 công cụ nhà phát triển được cài đặt.

CC -C FOO.C
NetBSD

Cờ trình biên dịch để tạopic-FPIC. VìelfHệ thống, trình biên dịch với cờ-sharedđược sử dụng để liên kết kèo bóng đá c1 thư viện được chia sẻ. Trên kèo bóng đá c1 hệ thống không phải là cũ,ld -bsharableđược sử dụng.

GCC -FPIC -C FOO.C
OpenBSD

Cờ trình biên dịch để tạopic-FPIC. ld -bsharableđược sử dụng để liên kết kèo bóng đá c1 thư viện được chia sẻ.

GCC -FPIC -C FOO.C
Solaris

Cờ trình biên dịch để tạopic-KPICVới trình biên dịch mặt trời và-FPICvớiGCC. Để liên kết kèo bóng đá c1 thư viện được chia sẻ, tùy chọn trình biên dịch là-gvới trình biên dịch hoặc thay thế-sharedvớiGCC.

cc -kpic -c foo.c

hoặc

GCC -FPIC -C FOO.C

TIP

Nếu điều này quá phức tạp đối với bạn, bạn nên xem xét sử dụnggnu libtool, che giấu sự khác biệt của nền tảng đằng sau giao diện thống nhất.

Tệp thư viện chia sẻ kết quả sau đó có thể được tải vàoPostgreSQL. Khi chỉ định tên tệp thànhTạo chức năngLệnh, người ta phải đặt tên cho tệp thư viện được chia sẻ, không phải tệp đối tượng trung gian. Lưu ý rằng tiện ích mở rộng thư viện chia sẻ tiêu chuẩn của hệ thống (thường là.sohoặc.SL) có thể được bỏ qua từtạo chức nănglệnh và thông thường nên được bỏ qua để có tính di động tốt nhất.

Tham khảo lạiPhần 36.10.1Giới thiệu về nơi máy chủ mong đợi tìm thấy kèo bóng đá c1 tệp thư viện được chia sẻ.

36.10.6. API máy chủ và hướng dẫn ổn định ABI#

Phần này chứa hướng dẫn cho kèo bóng đá c1 tác giả của phần mở rộng và kèo bóng đá c1 plugin máy chủ khác về tính ổn định API và ABI trongPostgreSQLMáy chủ.

36.10.6.1. Tổng quan#

ThePostgreSQLMáy chủ chứa một số API được phân loại tốt cho kèo bóng đá c1 plugin máy chủ, chẳng hạn như trình quản lý chức năng (fmgr, được mô tả trong chương này),SPI(Chương 45) và kèo bóng đá c1 móc khác nhau được thiết kế đặc biệt cho kèo bóng đá c1 phần mở rộng. kèo bóng đá c1 giao diện này được quản lý cẩn thận để ổn định và tương thích lâu dài.

Do đó, trong khi tận dụng kèo bóng đá c1 giao diện này là hợp lệ, thì một lần đi xa hơn từ đường dẫn tốt, thì người ta có thể gặp phải kèo bóng đá c1 vấn đề tương thích API hoặc ABI tại một số điểm. kèo bóng đá c1 tác giả mở rộng được khuyến khích cung cấp phản hồi về kèo bóng đá c1 yêu cầu của họ, để theo thời gian, vì kèo bóng đá c1 mẫu sử dụng mới phát sinh, có thể thêm kèo bóng đá c1 giao diện nhất định có thể được coi là ổn định hoặc mới, được thiết kế tốt hơn.

36.10.6.2. Khả năng tương thích API#

TheAPIhoặc giao diện lập trình ứng dụng, là giao diện được sử dụng tại thời điểm biên dịch.

36.10.6.2.1. Phiên bản chính#

khôngLời hứa tương thích API giữaPostgreSQLPhiên bản chính. Do đó, mã mở rộng có thể yêu cầu thay đổi mã nguồn để hoạt động với nhiều phiên bản chính.#if pg_version_num = 160000. kèo bóng đá c1 tiện ích mở rộng tinh vi sử dụng kèo bóng đá c1 giao diện ngoài kèo bóng đá c1 giao diện được phân loại tốt thường yêu cầu một vài thay đổi như vậy cho mỗi phiên bản máy chủ chính.

36.10.6.2.2. Phiên bản nhỏ#

PostgreSQLHãy nỗ lực để tránh bị hỏng API máy chủ trong kèo bóng đá c1 bản phát hành nhỏ. Nói chung, mã mở rộng biên dịch và làm việc với bản phát hành nhỏ cũng nên biên dịch và làm việc với bất kỳ bản phát hành nhỏ nào khác của cùng một phiên bản chính, quá khứ hoặc tương lai.

Khi thay đổiYêu cầu, nó sẽ được quản lý cẩn thận, đưa kèo bóng đá c1 yêu cầu của kèo bóng đá c1 phần mở rộng vào tài khoản. Những thay đổi như vậy sẽ được truyền đạt trong kèo bóng đá c1 ghi chú phát hành (Phụ lục E).

36.10.6.3. Khả năng tương thích ABI#

TheABIhoặc Giao diện nhị phân ứng dụng, là giao diện được sử dụng tại thời điểm chạy.

36.10.6.3.1. Phiên bản chính#

Máy chủ của kèo bóng đá c1 phiên bản chính khác nhau có cố ý không tương thích Abis. Do đó, kèo bóng đá c1 tiện ích mở rộng sử dụng API máy chủ phải được biên dịch lại cho mỗi bản phát hành chính.PG_MODULE_MAGIC(xemPhần 36.10.1) Đảm bảo mã đó được biên dịch cho một phiên bản chính sẽ bị từ chối bởi kèo bóng đá c1 phiên bản chính khác.

36.10.6.3.2. Phiên bản nhỏ#

PostgreSQLnỗ lực để tránh kèo bóng đá c1 máy chủ ABI bị hỏng trong kèo bóng đá c1 bản phát hành nhỏ. Nói chung, một tiện ích mở rộng được biên dịch với bất kỳ bản phát hành nhỏ nào sẽ hoạt động với bất kỳ bản phát hành nhỏ nào khác của cùng một phiên bản chính, quá khứ hoặc tương lai.

Khi thay đổiYêu cầu,POSTGRESQLSẽ chọn thay đổi ít xâm lấn nhất có thể, ví dụ bằng cách siết một trường mới vào không gian đệm hoặc nối nó vào cuối một cấu trúc. kèo bóng đá c1 loại thay đổi này không được tác động kèo bóng đá c1 tiện ích mở rộng trừ khi chúng sử dụng kèo bóng đá c1 mẫu mã rất bất thường.

Tuy nhiên, trong những trường hợp hiếm hoi, ngay cả những thay đổi không xâm lấn như vậy cũng có thể không thực tế hoặc không thể. Trong một sự kiện như vậy, sự thay đổi sẽ được quản lý cẩn thận, đưa kèo bóng đá c1 yêu cầu của kèo bóng đá c1 phần mở rộng vào tài khoản.Phụ lục E).

Tuy nhiên, lưu ý rằng nhiều phần của máy chủ không được thiết kế hoặc duy trì dưới dạng API được hưởng công khai (và trong hầu hết kèo bóng đá c1 trường hợp, ranh giới thực sự cũng không được xác định rõ). Nếu kèo bóng đá c1 nhu cầu khẩn cấp phát sinh, kèo bóng đá c1 thay đổi trong kèo bóng đá c1 phần đó sẽ được thực hiện một cách tự nhiên với ít xem xét về mã mở rộng hơn là những thay đổi trong kèo bóng đá c1 giao diện được xác định rõ ràng và được sử dụng rộng rãi.

Ngoài ra, trong trường hợp không có sự tự động phát hiện những thay đổi đó, đây không phải là kèo bóng đá c1 sự đảm bảo, nhưng về mặt lịch sử, những thay đổi phá vỡ như vậy là cực kỳ hiếm.

36.10.7. Đối số loại tổng hợp#

kèo bóng đá c1 loại tổng hợp không có bố cục cố định như cấu trúc C. kèo bóng đá c1 thể hiện của một loại tổng hợp có thể chứa kèo bóng đá c1 trường null.POSTGRESQLCung cấp giao diện chức năng để truy cập kèo bóng đá c1 trường của kèo bóng đá c1 loại tổng hợp từ C.

Giả sử chúng ta muốn viết kèo bóng đá c1 chức năng để trả lời truy vấn:

Chọn Tên, C_OverPaid (EMP, 1500) làm trả quá nhiều tiền

Sử dụng kèo bóng đá c1 quy ước gọi phiên bản-1, chúng ta có thể xác địnhc_overpaidAs:

#include "Postgres.h"

GetAttributionByNamePostgreSQLHàm hệ thống trả về kèo bóng đá c1 thuộc tính từ hàng được chỉ định. Nó có ba đối số: đối số của loạiHeaptupleHeaderđược chuyển vào kèo bóng đá c1, tên của thuộc tính mong muốn và tham số trả về cho biết thuộc tính có phải là NULL hay không.GetAttributebyNameTrả về ADatumGiá trị mà bạn có thể chuyển đổi sang kiểu dữ liệu phù hợp bằng cách sử dụng thích hợpDatumgetxxx()kèo bóng đá c1. Lưu ý rằng giá trị trả về là vô nghĩa nếu cờ null được đặt;

Ngoài ra còn cóGetAttributionByNum, chọn thuộc tính đích theo số cột thay vì tên.

Lệnh sau tuyên bố kèo bóng đá c1c_overpaidTrong SQL:

Tạo chức năng c_overpaid (EMP, Integer) Trả về BooleanThư mục/funcs ',' c_overpaid '

Thông báo chúng tôi đã sử dụngnghiêm ngặtđể chúng tôi không phải kiểm tra xem kèo bóng đá c1 đối số đầu vào có vô hiệu không.

36.10.8. Trả lại hàng (loại tổng hợp)#

Để trả về giá trị loại hoặc loại tổng hợp từ hàm ngôn ngữ C, bạn có thể sử dụng API đặc biệt cung cấp kèo bóng đá c1 macro và kèo bóng đá c1 hàm để ẩn hầu hết độ phức tạp của việc xây dựng kèo bóng đá c1 loại dữ liệu tổng hợp. Để sử dụng API này, tệp nguồn phải bao gồm:

#include "funcapi.h"

Có hai cách bạn có thể xây dựng giá trị dữ liệu tổng hợp (từ đó ATuplexông): Bạn có thể xây dựng nó từ một mảng kèo bóng đá c1 giá trị mốc hoặc từ một mảng kèo bóng đá c1 chuỗi C có thể được truyền đến kèo bóng đá c1 hàm chuyển đổi đầu vào của kèo bóng đá c1 loại dữ liệu cột của Tuple. Trong cả hai trường hợp, trước tiên bạn cần phải có được hoặc xây dựng mộttupledescMô tả cho cấu trúc tuple. Khi làm việc với Datums, bạn vượt quatupledescđếnBlesstupledesc, rồi gọiheap_form_tuplecho mỗi hàng. Khi làm việc với kèo bóng đá c1 chuỗi C, bạn vượt quatupledescđếntupledescgetattinmetadata, rồi gọibuildTupleFromCStringscho mỗi hàng. Trong trường hợp của một hàm trả về một tập hợp kèo bóng đá c1 bộ dữ liệu, tất cả kèo bóng đá c1 bước thiết lập đều có thể được thực hiện một lần trong cuộc gọi đầu tiên của hàm.

kèo bóng đá c1 số chức năng trợ giúp có sẵn để thiết lập cần thiếttupledesc. Cách được đề xuất để thực hiện điều này trong hầu hết kèo bóng đá c1 chức năng trả về kèo bóng đá c1 giá trị tổng hợp là gọi:

71926_72106

Vượt qua cùng kèo bóng đá c1fcinfoCấu trúc được chuyển đến chính chức năng gọi. (Tất nhiên điều này yêu cầu bạn sử dụng kèo bóng đá c1 quy ước gọi phiên bản 1.)resultTypeIDcó thể được chỉ định lànullhoặc là địa chỉ của biến cục bộ để nhận loại kết quả của kèo bóng đá c1 OID.resulttupledescnên là địa chỉ của kèo bóng đá c1 địa phươngtupledescBiến. Kiểm tra xem kết quả làTYPEFUNC_COMPISE; Nếu vậy,resulttupledescđã được lấp đầy với cần thiếttupledesc. (Nếu không, bạn có thể báo cáo lỗi dọc theo kèo bóng đá c1 dòngBản ghi trả về chức năng được gọi trong ngữ cảnh không thể chấp nhận bản ghi loạiKhăn.)

TIP

get_call_result_typecó thể giải quyết loại thực tế của kết quả hàm đa hình; Vì vậy, nó rất hữu ích trong kèo bóng đá c1 chức năng trả về kết quả đa hình vô hướng, không chỉ kèo bóng đá c1 chức năng trả về vật liệu tổng hợp.resultTypeIDĐầu ra chủ yếu hữu ích cho kèo bóng đá c1 chức năng trả về vô hướng đa hình.

Lưu ý

GET_CALL_RESULT_TYPECó anh chị emGET_EXPR_RESULT_TYPE, có thể được sử dụng để giải quyết loại đầu ra dự kiến ​​cho một cuộc gọi kèo bóng đá c1 được biểu thị bằng cây biểu thức. Điều này có thể được sử dụng khi cố gắng xác định loại kết quả từ bên ngoài chức năng.get_func_result_type, có thể được sử dụng khi chỉ có OID của hàm. Tuy nhiên, kèo bóng đá c1 chức năng này không thể xử lý kèo bóng đá c1 chức năng được khai báo để trả vềRecordget_func_result_typeKhông thể giải quyết kèo bóng đá c1 loại đa hình, vì vậy bạn nên sử dụng một cách ưu tiênget_call_result_type.

kèo bóng đá c1 chức năng cũ hơn, hiện đang được ghi nhận để có đượctupledescS là:

74372_74431

để nhậntupledescĐối với loại hàng của mối quan hệ được đặt tên và:

74573_74634

để nhậntupledescDựa trên kèo bóng đá c1 loại oid. Điều này có thể được sử dụng để có được kèo bóng đá c1tupledescĐối với loại cơ sở hoặc loại tổng hợp. Nó sẽ không hoạt động cho một kèo bóng đá c1 trả vềRecordTuy nhiên, và nó không thể giải quyết kèo bóng đá c1 loại đa hình.

kèo bóng đá c1 khi bạn cótupledesc, gọi:

75063_75110

Nếu bạn có kế hoạch làm việc với kèo bóng đá c1 mốc dữ liệu, hoặc:

75195_75258

Nếu bạn có kế hoạch làm việc với kèo bóng đá c1 chuỗi C. Nếu bạn đang viết một bộ trả lại chức năng, bạn có thể lưu kết quả của kèo bóng đá c1 chức năng này trongfunccallcontextCấu trúc - Sử dụngTuple_deschoặcAttinMetatrường tương ứng.

Khi làm việc với mốc dữ liệu, sử dụng:

75658_75735

Để xây dựng AHeaptupleđã cho dữ liệu người dùng ở dạng mốc dữ liệu.

Khi làm việc với kèo bóng đá c1 chuỗi C, sử dụng:

75912_75989

Để xây dựng AHeaptupleĐã cho dữ liệu người dùng ở dạng chuỗi C.Giá trịlà một mảng chuỗi C, một cho mỗi thuộc tính của hàng trả lại. Mỗi chuỗi C phải ở dạng dự kiến ​​bởi kèo bóng đá c1 đầu vào của kiểu dữ liệu thuộc tính.Giá trịMảng phải được đặt thànhnull. Chức năng này sẽ cần được gọi lại cho mỗi hàng bạn trở lại.

Khi bạn đã xây dựng kèo bóng đá c1 tuple để trở về từ chức năng của mình, nó phải được chuyển đổi thành ADatum. Sử dụng:

76733_76771

Để chuyển đổi AHeaptuplethành kèo bóng đá c1 mốc thời gian hợp lệ. Cái nàyDatumCó thể được trả về trực tiếp nếu bạn có ý định trả về chỉ một hàng hoặc nó có thể được sử dụng làm giá trị trả về hiện tại trong kèo bóng đá c1 hoàn trả lại.

kèo bóng đá c1 ví dụ xuất hiện trong phần tiếp theo.

36.10.9. Trả về kèo bóng đá c1 bộ#

kèo bóng đá c1 hàm ngôn ngữ C có hai tùy chọn để trả về kèo bóng đá c1 bộ (nhiều hàng). Trong một phương thức, được gọi làValuePercallMODE, Hàm hoàn trả đã được gọi là lặp đi lặp lại (chuyển kèo bóng đá c1 đối số giống nhau mỗi lần) và nó trả về một hàng mới trên mỗi cuộc gọi, cho đến khi nó không còn hàng để trả về và tín hiệu bằng cách trả về NULL. Chức năng trả lại thiết lập (SRF) Do đó, phải lưu đủ trạng thái qua kèo bóng đá c1 cuộc gọi để nhớ những gì nó đang làm và trả về mục tiếp theo chính xác trên mỗi cuộc gọi. Trong phương thức khác, được gọi làvật chất hóachế độ, SRF điền và trả về kèo bóng đá c1 đối tượng tuplestore chứa toàn bộ kết quả của nó; sau đó chỉ có kèo bóng đá c1 cuộc gọi xảy ra cho toàn bộ kết quả và không cần trạng thái liên hệ.

Khi sử dụng chế độ ValuePerCall, điều quan trọng cần nhớ là truy vấn không được đảm bảo sẽ được chạy để hoàn thành; nghĩa là, do kèo bóng đá c1 tùy chọn nhưGiới hạn, Người thực thi có thể ngừng thực hiện kèo bóng đá c1 cuộc gọi đến chức năng hoàn trả trước khi tất cả kèo bóng đá c1 hàng đã được tìm nạp. Điều này có nghĩa là không an toàn khi thực hiện kèo bóng đá c1 hoạt động dọn dẹp trong cuộc gọi cuối cùng, bởi vì điều đó có thể không bao giờ xảy ra.

Phần còn lại của phần này ghi lại một tập hợp kèo bóng đá c1 macro trợ giúp thường được sử dụng (mặc dù không bắt buộc phải được sử dụng) cho SRF bằng chế độ ValuePercall. Chi tiết bổ sung về chế độ vật chất hóa có thể được tìm thấy trongSRC/Backend/Utils/fmgr/readme. Ngoài ra,Đóng gópMô -đun trongPOSTGRESQLPhân phối nguồn chứa nhiều ví dụ về SRF bằng cả chế độ ValuePercall và Meterize.

Để sử dụng kèo bóng đá c1 macro hỗ trợ ValuePercall được mô tả ở đây, bao gồmfuncapi.h. kèo bóng đá c1 macro này hoạt động với một cấu trúcfunccallcontextchứa trạng thái cần được lưu qua kèo bóng đá c1 cuộc gọi. Trong cuộc gọi SRF,fcinfo- flinfo- fn_extrađược sử dụng để giữ kèo bóng đá c1 con trỏ tớifunccallcontextqua kèo bóng đá c1 cuộc gọi. kèo bóng đá c1 macro tự động điền vào trường đó khi sử dụng đầu tiên và mong đợi tìm thấy cùng một con trỏ ở đó trên kèo bóng đá c1 mục đích sử dụng tiếp theo.

Typedef struct funccallcontext

Macro được sử dụng bởiSRFSử dụng cơ sở hạ tầng này là:

srf_is_firstcall ()

Sử dụng điều này để xác định xem chức năng của bạn có được gọi cho lần đầu tiên hay lần tiếp theo không. Trong cuộc gọi đầu tiên (chỉ), cuộc gọi:

srf_firstcall_init ()

Để khởi tạofunccallcontext. Trên mọi cuộc gọi chức năng, bao gồm cuộc gọi đầu tiên, cuộc gọi:

srf_percall_setup ()

Để thiết lập để sử dụngfunccallcontext.

Nếu chức năng của bạn có dữ liệu để trả về trong cuộc gọi hiện tại, hãy sử dụng:

srf_return_next (funcctx, result)

Để trả lại cho người gọi. (resultphải thuộc loạiDatum82632_82759

srf_return_done (funcctx)

Để dọn dẹp và kết thúcSRF.

Bối cảnh bộ nhớ hiện tại khiSRFđược gọi là một bối cảnh thoáng qua sẽ được xóa giữa kèo bóng đá c1 cuộc gọi. Điều này có nghĩa là bạn không cần gọiPFREETrên mọi thứ bạn đã phân bổ bằng cách sử dụngPalloC; Nó sẽ biến mất dù sao.Multi_call_memory_ctxlà kèo bóng đá c1 vị trí phù hợp cho bất kỳ dữ liệu nào cần tồn tại cho đến khiSRFĐược hoàn thành chạy. Trong hầu hết kèo bóng đá c1 trường hợp, điều này có nghĩa là bạn nên chuyển thànhMulti_call_memory_ctxTrong khi thực hiện thiết lập cuộc gọi đầu tiên. Sử dụngfuncctx- user_fctxĐể giữ kèo bóng đá c1 con trỏ đến bất kỳ cấu trúc dữ liệu gọi chéo nào như vậy. (Dữ liệu bạn phân bổ trongmulti_call_memory_ctxsẽ tự động biến mất khi truy vấn kết thúc, do đó, không cần thiết phải giải phóng dữ liệu đó bằng tay.)

CẢNH BÁO

Trong khi kèo bóng đá c1 đối số thực tế cho hàm vẫn không thay đổi giữa kèo bóng đá c1 cuộc gọi, nếu bạn detoast kèo bóng đá c1 giá trị đối số (thường được thực hiện trong suốt bởipg_getarg_xxxMacro) trong bối cảnh thoáng qua sau đó kèo bóng đá c1 bản sao bị khử sẽ được giải phóng trên mỗi chu kỳ. Theo đó, nếu bạn tiếp tục tham chiếu đến kèo bóng đá c1 giá trị đó trong của bạnuser_fctx, bạn phải sao chép chúng vàomulti_call_memory_ctxSau khi detoasting hoặc đảm bảo rằng bạn chỉ định kèo bóng đá c1 giá trị trong bối cảnh đó.

kèo bóng đá c1 ví dụ giả giả hoàn chỉnh trông giống như sau:

DatumKhai báo thêm khi cầnif (srf_is_firstcall ())Mã người dùng
        Nếu trả về composite
            Build tupledesc và có lẽ là attinmetadata
        endif trả về composite
        Mã người dùngMemoryContextSwitchTo (OldContext);Mã người dùngfuncctx = srf_percall_setup ();Mã người dùng/ * Đây chỉ là kèo bóng đá c1 cách chúng ta có thể kiểm tra xem chúng ta đã hoàn thành: */Mã người dùng
        có được dữ liệu kết quảsrf_return_next (funcctx, result);

kèo bóng đá c1 ví dụ hoàn chỉnh về đơn giảnSRFTrả về loại tổng hợp trông giống như:

pg_function_info_v1 (retcposite);

kèo bóng đá c1 cách để khai báo chức năng này trong SQL là:

Tạo loại __retComposite AS (F1 Integer, F2 Integer, F3 Integer);FileName',' retcposite '

Một cách khác là sử dụng kèo bóng đá c1 tham số:

Tạo hoặc thay thế chức năng retcposite (tính bằng số nguyên, trong số nguyên,FileName',' retcposite '

Lưu ý rằng trong phương pháp này, loại đầu ra của kèo bóng đá c1 chính thức là một ẩn danhRecordloại.

36.10.10. kèo bóng đá c1 đối số đa hình và loại trả về#

kèo bóng đá c1 hàm ngôn ngữ C có thể được khai báo để chấp nhận và trả về kèo bóng đá c1 loại đa hình được mô tả trongPhần 36.2.5. Khi kèo bóng đá c1 đối số hoặc loại trả về của hàm được định nghĩa là kèo bóng đá c1 loại đa hình, tác giả chức năng không thể biết trước kiểu dữ liệu nào sẽ được gọi với hoặc cần quay lại.fmgr.hĐể cho phép chức năng phiên bản 1 C khám phá kèo bóng đá c1 loại dữ liệu thực tế của kèo bóng đá c1 đối số và loại nó dự kiến ​​sẽ trả về. kèo bóng đá c1 thói quen được gọi làget_fn_expr_rettype (fmgrinfo *flinfo)get_fn_expr_argtype (fmgrinfo *flinfo, int argnum). Họ trả về kết quả hoặc loại đối số oid hoặckhông hợp lệNếu thông tin không có sẵn. Cấu trúcflinfothường được truy cập làfcinfo- flinfo. Tham sốArgnumbằng không.GET_CALL_RESULT_TYPEcũng có thể được sử dụng thay thế choget_fn_expr_rettype. Ngoài ra còn cóGET_FN_EXPR_VARIADIC, có thể được sử dụng để tìm hiểu xem kèo bóng đá c1 đối số variadic đã được hợp nhất thành một mảng. Điều này chủ yếu hữu ích choVariadic "Any"kèo bóng đá c1 chức năng, vì sự hợp nhất đó sẽ luôn xảy ra đối với kèo bóng đá c1 hàm variadic Lấy kèo bóng đá c1 loại mảng thông thường.

Ví dụ: giả sử chúng ta muốn viết một kèo bóng đá c1 để chấp nhận một yếu tố duy nhất thuộc bất kỳ loại nào và trả về một mảng một chiều thuộc loại đó:

pg_function_info_v1 (make_array);

Lệnh sau tuyên bố kèo bóng đá c1make_arraytrong SQL:

Tạo chức năng Make_array (AnyEuity) trả về AnyArrayThư mục/funcs ',' make_array '

Có một biến thể đa hình chỉ có sẵn cho kèo bóng đá c1 hàm ngôn ngữ C: Chúng có thể được tuyên bố lấy kèo bóng đá c1 tham số loại"bất kỳ". (Lưu ý rằng tên loại này phải được trích dẫn kép, vì nó cũng là kèo bóng đá c1 từ dành riêng cho SQL.) Điều này hoạt động nhưAnyEuityNgoại trừ việc nó không hạn chế khác nhau"bất kỳ"Đối số là cùng loại, cũng không giúp xác định loại kết quả của kèo bóng đá c1. kèo bóng đá c1 ngôn ngữ C cũng có thể khai báo tham số cuối cùng của nó làVariadic "Any". Điều này sẽ phù hợp với kèo bóng đá c1 hoặc nhiều đối số thực tế thuộc bất kỳ loại nào (không nhất thiết phải cùng loại).khôngđược thu thập thành một mảng như xảy ra với kèo bóng đá c1 hàm variadic bình thường; Chúng sẽ được chuyển cho chức năng riêng biệt.pg_nargs ()Macro và kèo bóng đá c1 phương thức được mô tả ở trên phải được sử dụng để xác định số lượng đối số thực tế và kèo bóng đá c1 loại của chúng khi sử dụng tính năng này. Ngoài ra, người dùng của một chức năng như vậy có thể muốn sử dụngVariadicTừ khóa trong cuộc gọi chức năng của họ, với kỳ vọng rằng hàm sẽ coi kèo bóng đá c1 phần tử mảng là kèo bóng đá c1 đối số riêng biệt. Bản thân chức năng phải thực hiện hành vi đó nếu muốn, sau khi sử dụngGET_FN_EXPR_VARIADICĐể phát hiện ra rằng đối số thực tế được đánh dấu bằngVariadic.

36.10.11. Bộ nhớ chia sẻ#

36.10.11.1. Yêu cầu bộ nhớ được chia sẻ khi khởi động#

add-in có thể đặt trước bộ nhớ chia sẻ khi khởi động máy chủ. Để làm như vậy, thư viện chia sẻ của bổ trợ phải được tải trước bằng cách chỉ định nó trongshared_preload_l Libries. Thư viện chia sẻ cũng sẽ đăng ký kèo bóng đá c1SHMEM_REQUEST_HOOKTrong nó_pg_initkèo bóng đá c1. Cái nàySHMEM_REQUEST_HOOKCó thể dự trữ bộ nhớ chia sẻ bằng cách gọi:

void requestaddinshmemspace (kích thước kích thước)

Mỗi phụ trợ sẽ có được kèo bóng đá c1 con trỏ tới bộ nhớ chia sẻ dành riêng bằng cách gọi:

96620_96690

Nếu kèo bóng đá c1 này đặtFoundPtrđếnSai, người gọi nên tiến hành khởi tạo nội dung của bộ nhớ chia sẻ dành riêng. Nếu nhưFoundPtrđược đặt thànhTRUE, bộ nhớ chia sẻ đã được khởi tạo bởi kèo bóng đá c1 phụ trợ khác và người gọi không cần phải khởi tạo thêm.

Để tránh kèo bóng đá c1 điều kiện chủng tộc, mỗi phụ trợ nên sử dụng LWLOCKaddinshmeminitlockKhi khởi tạo phân bổ bộ nhớ chia sẻ, như được hiển thị ở đây:

MyStruct static *ptr = null;

shmem_startup_hookCung cấp một nơi thuận tiện cho mã khởi tạo, nhưng không yêu cầu hoàn toàn là tất cả kèo bóng đá c1 mã đó được đặt trong móc này. Mỗi phụ trợ sẽ thực thi đã đăng kýSHMEM_STARTUP_HOOKNgay sau khi nó gắn vào bộ nhớ chia sẻ. Lưu ý rằng kèo bóng đá c1 tiện ích bổ sung vẫn sẽ có đượcAddInshmeminitLockTrong cái móc này, như được hiển thị trong ví dụ trên.

kèo bóng đá c1 ví dụ về Ashmem_request_hookshmem_startup_hookcó thể được tìm thấy trong98260_98309trongPostgreSQLCây nguồn.

36.10.11.2. Yêu cầu bộ nhớ được chia sẻ sau khi khởi động#

Có kèo bóng đá c1 phương pháp khác, linh hoạt hơn để bảo lưu bộ nhớ chia sẻ có thể được thực hiện sau khi khởi động máy chủ và bên ngoàiSHMEM_REQUEST_HOOK. Để làm như vậy, mỗi phụ trợ sẽ sử dụng bộ nhớ chia sẻ sẽ có được kèo bóng đá c1 con trỏ cho nó bằng cách gọi:

VOID *

Nếu kèo bóng đá c1 phân đoạn bộ nhớ chia sẻ động với tên đã cho chưa tồn tại, chức năng này sẽ phân bổ nó và khởi tạo nó với được cung cấpinit_callbackkèo bóng đá c1 gọi lại. Nếu phân đoạn đã được phân bổ và khởi tạo bởi một phụ trợ khác, chức năng này chỉ cần gắn phân đoạn bộ nhớ chia sẻ động hiện có vào phần phụ trợ hiện tại.

Không giống như bộ nhớ chia sẻ được dành riêng khi khởi động máy chủ, không cần phải có đượcAddInshmeminitLockhoặc hành động khác để tránh kèo bóng đá c1 điều kiện đua khi đặt bộ nhớ chia sẻ vớigetNamedDSMSegment. Hàm này đảm bảo rằng chỉ có một phụ trợ phân bổ và khởi tạo phân đoạn và tất cả kèo bóng đá c1 phụ trợ khác nhận được một con trỏ tới phân đoạn được phân bổ và khởi tạo đầy đủ.

kèo bóng đá c1 ví dụ sử dụng hoàn chỉnh củaGetNamedDsMsegmentcó thể được tìm thấy trongsrc/test/modules/test_dsm_registry/test_dsm_registry.ctrongPostgreSQLCây nguồn.

36.10.12. Lwlocks#

36.10.12.1. Yêu cầu LWLOCKS khi khởi động#

add-in có thể bảo lưu LWlocks khi khởi động máy chủ. Như với bộ nhớ được chia sẻ được dành riêng khi khởi động máy chủ, thư viện chia sẻ của bổ trợ phải được tải trước bằng cách chỉ định nó trongshared_preload_l Libriesvà Thư viện được chia sẻ nên đăng ký ASHMEM_REQUEST_HOOKTrong nó_pg_initkèo bóng đá c1. Cái nàyshmem_request_hookCó thể đặt trước LWLOCKS bằng cách gọi:

void requestNamedLwlockTranche (const char *tranche_name, int num_lwlocks)

Điều này đảm bảo rằng kèo bóng đá c1 mảngnum_lwlockslwlocks có sẵn dưới tênTranche_name. kèo bóng đá c1 con trỏ đến mảng này có thể được lấy bằng cách gọi:

lwlockpadded *getNamedLwlockTranche (const char *tranche_name)

36.10.12.2. Yêu cầu LWlocks sau khi khởi động#

102237_102351shmem_request_hook. Để làm như vậy, đầu tiên phân bổ ATranche_idbằng cách gọi:

int lwlocknewtrancheid (void)

Tiếp theo, khởi tạo từng lwlock, vượt qua mớitranche_idnhư kèo bóng đá c1 đối số:

void lwlockinitialize (lwlock *khóa, int tranche_id)

Tương tự như bộ nhớ chia sẻ, mỗi phụ trợ phải đảm bảo rằng chỉ kèo bóng đá c1 quy trình phân bổ mớiTranche_idvà khởi tạo từng lwlock mới. Một cách để làm điều này là chỉ gọi kèo bóng đá c1 chức năng này trong mã khởi tạo bộ nhớ được chia sẻ của bạn vớiAddInshmeminitLockĐược tổ chức độc quyền. Nếu sử dụngGetNamedDSMSegment, Gọi kèo bóng đá c1 chức năng này tronginit_callbackHàm gọi lại là đủ để tránh kèo bóng đá c1 điều kiện chủng tộc.

Cuối cùng, mỗi phụ trợ sử dụngTranche_idnên liên kết nó vớitranche_namebằng cách gọi:

void lwlockregistertranche (int tranche_id, const char *tranche_name)

kèo bóng đá c1 ví dụ sử dụng hoàn chỉnh củalwlocknewtrancheid, lwlockinitializelwlockregistertrancheCó thể tìm thấy trong103806_103840trongPostgreSQLCây nguồn.

36.10.13. Sự kiện chờ tùy chỉnh#

add-in có thể xác định kèo bóng đá c1 sự kiện chờ tùy chỉnh theo loại sự kiện chờ đợiMở rộngbằng cách gọi:

104360_104421

Sự kiện chờ được liên kết với chuỗi tùy chỉnh hướng tới người dùng. kèo bóng đá c1 ví dụ có thể được tìm thấy trongsrc/test/modules/worker_spiTrong cây nguồn PostgreSQL.

Sự kiện chờ tùy chỉnh có thể được xem trongpg_stat_activity:

=# Chọn Wait_Event_Type, Wait_Event từ pg_stat_activity

36.10.14. Điểm tiêm#

kèo bóng đá c1 điểm tiêm với đã chotênđược khai báo bằng macro:

injection_point (tên);

Có một vài điểm tiêm đã được khai báo tại kèo bóng đá c1 điểm chiến lược trong mã máy chủ. Sau khi thêm một điểm tiêm mới, mã cần được biên dịch để điểm tiêm đó có sẵn trong nhị phân.

Thực hiện một điểm tiêm có thể yêu cầu phân bổ một lượng nhỏ bộ nhớ, có thể thất bại. Nếu bạn cần có một điểm tiêm trong một phần quan trọng trong đó việc phân bổ động không được phép, bạn có thể sử dụng phương pháp hai bước với kèo bóng đá c1 macro sau:

injection_point_load (tên);

Trước khi vào phần quan trọng, hãy gọiinjection_point_load. Nó kiểm tra trạng thái bộ nhớ được chia sẻ và tải cuộc gọi lại vào bộ nhớ phụ trợ nếu nó hoạt động.injection_point_cachedĐể thực hiện cuộc gọi lại.

add-in có thể đính kèm kèo bóng đá c1 cuộc gọi lại vào điểm tiêm đã được khai báo bằng cách gọi:

106754_107033

tênlà tên của điểm tiêm, khi đạt được trong quá trình thực thi sẽ thực thichức năngĐược tải từThư viện. private_datalà khu vực riêng tư có kích thướcprivate_data_sizeĐược đưa ra làm đối số cho cuộc gọi lại khi được thực thi.

Đây là kèo bóng đá c1 ví dụ về cuộc gọi lại choInfectionPointCallback:

void tĩnh

Cuộc gọi lại này in thông báo vào nhật ký lỗi máy chủ với mức độ nghiêm trọngThông báo, nhưng kèo bóng đá c1 cuộc gọi lại có thể thực hiện logic phức tạp hơn.

kèo bóng đá c1 cách khác để xác định hành động cần thực hiện khi đạt được điểm tiêm là thêm mã kiểm tra cùng với mã nguồn thông thường. Điều này có thể hữu ích nếu hành động, ví dụ:is_injection_point_attachedMacro sau đó có thể được sử dụng để kiểm tra xem điểm tiêm có được đính kèm không, ví dụ:

#ifdef use_injection_points

Lưu ý rằng cuộc gọi lại được gắn vào điểm tiêm sẽ không được thực hiện bởiis_injection_point_attachedMacro. Nếu bạn muốn thực hiện cuộc gọi lại, bạn cũng phải gọiinjection_point_cachedGiống như trong ví dụ trên.

Tùy chọn, có thể tách kèo bóng đá c1 điểm tiêm bằng cách gọi:

extern bool injectionPointDetach (const char *name);

Khi thành công,TRUEđược trả về,Sainếu không.

Một cuộc gọi lại được gắn vào một điểm tiêm có sẵn trên tất cả kèo bóng đá c1 phụ trợ bao gồm kèo bóng đá c1 phụ trợ bắt đầu sauInfectionPointattachđược gọi. Nó vẫn được gắn trong khi máy chủ đang chạy hoặc cho đến khi điểm tiêm được tách ra bằng cách sử dụngInfectionPointDetach.

kèo bóng đá c1 ví dụ có thể được tìm thấy trongsrc/test/modules/infTrong cây nguồn PostgreSQL.

Kích hoạt điểm tiêm yêu cầuvớiCấu hìnhhoặc-dinjection_points = truevớiMeson.

36.10.15. Thống kê tích lũy tùy chỉnh#

Có thể được viết bằng tiếng c để sử dụng kèo bóng đá c1 loại thống kê tích lũy tùy chỉnh được đăng ký trongHệ thống thống kê tích lũy.

Đầu tiên, xác định APGSTAT_KINDINFOBao gồm tất cả kèo bóng đá c1 thông tin liên quan đến loại tùy chỉnh đã đăng ký. Ví dụ:

const static pgstat_kindinfo Custom_stats =

Sau đó, mỗi phụ trợ cần sử dụng loại tùy chỉnh này cần phải đăng ký vớiPGSTAT_REGISTER_KINDvà một ID duy nhất được sử dụng để lưu trữ kèo bóng đá c1 mục liên quan đến loại thống kê này:

extern pgstat_kind pgstat_register_kind (pgstat_kind loại,

Trong khi phát triển tiện ích mở rộng mới, hãy sử dụngpgstat_kind_experimentalchoKind. Khi bạn đã sẵn sàng để phát hành tiện ích mở rộng cho người dùng, hãy đặt kèo bóng đá c1 ID tử tạiThống kê tích lũy tùy chỉnhTrang.

Chi tiết của API choPGSTAT_KINDINFOCó thể tìm thấy trong112020_112057.

Loại thống kê được đăng ký được liên kết với kèo bóng đá c1 tên và ID duy nhất được chia sẻ trên máy chủ trong bộ nhớ chia sẻ. Mỗi phụ trợ bằng cách sử dụng kèo bóng đá c1 loại thống kê tùy chỉnh duy trì bộ đệm cục bộ lưu trữ thông tin của mỗi tùy chỉnhPGSTAT_KINDINFO.

Đặt mô -đun mở rộng triển khai loại thống kê tích lũy tùy chỉnh trongshared_preload_l Libriesđể nó được tải sớm trong khiPostgreSQLKhởi động.

kèo bóng đá c1 ví dụ mô tả cách đăng ký và sử dụng số liệu thống kê tùy chỉnh có thể được tìm thấy trongsrc/test/modules/inf.

36.10.16. Sử dụng C ++ để mở rộng#

mặc dùPOSTGRESQLphụ trợ được viết bằng C, có thể ghi kèo bóng đá c1 tiện ích mở rộng trong C ++ nếu kèo bóng đá c1 hướng dẫn này được tuân thủ:

  • Tất cả kèo bóng đá c1 chức năng được truy cập bởi phần phụ trợ phải trình bày giao diện C cho phần phụ trợ; kèo bóng đá c1 chức năng C này sau đó có thể gọi kèo bóng đá c1 hàm C ++.Extern CLiên kết là cần thiết cho kèo bóng đá c1 chức năng được truy cập phụ trợ. Điều này cũng cần thiết cho bất kỳ chức năng nào được truyền dưới dạng con trỏ giữa mã phụ trợ và mã C ++.

  • Bộ nhớ miễn phí bằng phương pháp giải quyết thích hợp. Ví dụ: hầu hết bộ nhớ phụ trợ được phân bổ bằng cách sử dụngpalloc (), vì vậy hãy sử dụngpfree ()Để giải phóng nó. Sử dụng C ++XóaTrong những trường hợp như vậy sẽ thất bại.

  • Ngăn chặn kèo bóng đá c1 ngoại lệ truyền vào mã C (sử dụng khối bắt tất cả ở cấp cao nhất của tất cảExtern Cchức năng). Điều này là cần thiết ngay cả khi mã C ++ không ném rõ ràng bất kỳ ngoại lệ nào, bởi vì kèo bóng đá c1 sự kiện như ngoài bộ nhớ vẫn có thể đưa ra kèo bóng đá c1 ngoại lệ.-FNO-EXCEPTIONĐể loại bỏ hoàn toàn kèo bóng đá c1 ngoại lệ; Trong những trường hợp như vậy, bạn phải kiểm tra kèo bóng đá c1 lỗi trong mã C ++ của mình, ví dụ: kiểm tra null được trả về bởinew ().

  • Nếu gọi kèo bóng đá c1 chức năng phụ trợ từ mã C ++, hãy chắc chắn rằng ngăn xếp cuộc gọi C ++ chỉ chứa kèo bóng đá c1 cấu trúc dữ liệu cũ đơn giản (Pod). Điều này là cần thiết bởi vì lỗi phụ trợ tạo ra kèo bóng đá c1 xalongjmp ()115105_115176

Tóm lại, tốt nhất là đặt mã C ++ phía sau kèo bóng đá c1 bức tường củaExtern Ckèo bóng đá c1 hàm giao diện cho phần phụ trợ và tránh ngoại lệ, bộ nhớ và gọi rò rỉ ngăn xếp.