fix SPI build

This commit is contained in:
Christian Grothoff 2023-04-16 22:07:36 +02:00
parent ade7586c30
commit 8463572bea
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 107 additions and 125 deletions

View File

@ -1,6 +1,7 @@
EXTENSION = own_test EXTENSION = own_test
MODULES = own_test MODULES = own_test
DATA = own_test.sql DATA = own_test.sql
PG_CPPFLAGS = -I /usr/include/postgresql
# postgresql build stuff # postgresql build stuff
PG_CONFIG = pg_config PG_CONFIG = pg_config

View File

@ -1,41 +1,37 @@
Server Programming Interface (SPI) Server Programming Interface (SPI)
Dependencies: Overview
=============
These are the direct dependencies for running SPI functions :
Step 1:
"postgresql-server-dev-<depends on your postgresql version>"
-- sudo apt-get install libpq-dev postgresql-server-dev-13
Step 2:
To solve gssapi/gssapi.h, use the following command:
apt-get install libkrb5-dev
Step 3:
apt-cache search openssl | grep -- -dev
apt-get install libssl-dev
Compile:
======== ========
gcc -shared -o <file_name>.so <file_name>.c
CALL FUNCTIONS: This folder contains results from an experiment by Joseph Xu
=============== to use the Postgres SPI. They are not currently used at all
by the GNU Taler exchange.
psql -c "SELECT <function_name>();" db_name
Structure: Dependencies
========== ============
usr/include/postgres/ These are the direct dependencies for compiling the code:
usr/include/postgres/13/server/ # apt-get install libpq-dev postgresql-server-dev-13
# apt-get install libkrb5-dev
# apt-get install libssl-dev
make
make install Compilation
psql ===========
$ make
Loading functions
=================
# make install
$ psql "$DB_NAME" < own_test.sql
Calling functions
==================
$ psql -c "SELECT $FUNCTION_NAME($ARGS);" "$DB_NAME"

View File

@ -2,17 +2,17 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <libpq-fe.h> #include <postgresql/libpq-fe.h>
#include <internal/libpq-int.h> #include <libpq-int.h>
#include <catalog/pg_type.h> #include <catalog/pg_type.h>
#include <executor/spi.h> #include <executor/spi.h>
#include <funcapi.h> #include <funcapi.h>
#include <fmgr.h> #include <fmgr.h>
#include <utils/builtins.h> #include <utils/builtins.h>
#include "utils/array.h" #include <utils/array.h>
#include <sys/time.h> #include <sys/time.h>
#include "utils/numeric.h" #include <utils/numeric.h>
#include "utils/timestamp.h" #include <utils/timestamp.h>
#include <utils/bytea.h> #include <utils/bytea.h>
#ifdef PG_MODULE_MAGIC #ifdef PG_MODULE_MAGIC
@ -66,7 +66,7 @@ pg_spi_prepare_example (PG_FUNCTION_ARGS)
{ {
if (prepared_plan == NULL) if (prepared_plan == NULL)
{ {
new_plan = SPI_prepare ("SELECT 1 FROM joseph_test.X", 0, NULL); new_plan = SPI_prepare ("SELECT 1 FROM X", 0, NULL);
prepared_plan = SPI_saveplan (new_plan); prepared_plan = SPI_saveplan (new_plan);
if (prepared_plan == NULL) if (prepared_plan == NULL)
@ -112,7 +112,7 @@ pg_spi_prepare_example_without_saveplan (PG_FUNCTION_ARGS)
} }
{ {
new_plan = SPI_prepare ("SELECT 1 FROM joseph_test.X", 0, NULL); new_plan = SPI_prepare ("SELECT 1 FROM X", 0, NULL);
ret = SPI_execute_plan (new_plan, NULL, 0,false, 0); ret = SPI_execute_plan (new_plan, NULL, 0,false, 0);
if (ret != SPI_OK_SELECT) if (ret != SPI_OK_SELECT)
{ {
@ -142,7 +142,7 @@ Datum
pg_spi_select_from_x (PG_FUNCTION_ARGS) pg_spi_select_from_x (PG_FUNCTION_ARGS)
{ {
int ret; int ret;
char *query = "SELECT 1 FROM joseph_test.X"; char *query = "SELECT 1 FROM X";
uint64 proc; uint64 proc;
ret = SPI_connect (); ret = SPI_connect ();
@ -172,7 +172,7 @@ pg_spi_insert_int (PG_FUNCTION_ARGS)
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
Datum values[1]; Datum values[1];
char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; char *query = "INSERT INTO X (a) VALUES ($1)";
ret = SPI_connect (); ret = SPI_connect ();
if (ret != SPI_OK_CONNECT) if (ret != SPI_OK_CONNECT)
@ -204,7 +204,7 @@ pg_spi_prepare_insert (PG_FUNCTION_ARGS)
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
Datum values[1]; Datum values[1];
char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; const char *query = "INSERT INTO X (a) VALUES ($1)";
SPIPlanPtr new_plan; SPIPlanPtr new_plan;
ret = SPI_connect (); ret = SPI_connect ();
if (ret != SPI_OK_CONNECT) if (ret != SPI_OK_CONNECT)
@ -252,7 +252,7 @@ pg_spi_prepare_insert_bytea(PG_FUNCTION_ARGS)
Datum values[1]; Datum values[1];
Oid argtypes2[1]; Oid argtypes2[1];
Datum val[1]; Datum val[1];
char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; char *query = "INSERT INTO X (a) VALUES ($1)";
SPIPlanPtr new_plan; SPIPlanPtr new_plan;
ret = SPI_connect(); ret = SPI_connect();
if (ret != SPI_OK_CONNECT) if (ret != SPI_OK_CONNECT)
@ -296,7 +296,7 @@ pg_spi_prepare_insert_without_saveplan (PG_FUNCTION_ARGS)
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
Datum values[1]; Datum values[1];
char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)"; const char *query = "INSERT INTO X (a) VALUES ($1)";
SPIPlanPtr new_plan; SPIPlanPtr new_plan;
ret = SPI_connect (); ret = SPI_connect ();
if (ret != SPI_OK_CONNECT) if (ret != SPI_OK_CONNECT)
@ -333,7 +333,7 @@ pg_spi_select_pair_from_y(PG_FUNCTION_ARGS)
int ret; int ret;
valuest result; valuest result;
bool isnull; bool isnull;
char *query = "SELECT 1,1 FROM joseph_test.Y"; char *query = "SELECT 1,1 FROM Y";
result.col1 = 0; result.col1 = 0;
result.col2 = 0; result.col2 = 0;
@ -368,7 +368,7 @@ pg_spi_select_with_cond(PG_FUNCTION_ARGS)
Oid argtypes[1]; Oid argtypes[1];
Datum values[1]; Datum values[1];
uint64 proc; uint64 proc;
query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; query = "SELECT col1 FROM Y WHERE col2 = $1";
ret = SPI_connect(); ret = SPI_connect();
if (ret != SPI_OK_CONNECT) { if (ret != SPI_OK_CONNECT) {
@ -401,7 +401,7 @@ Datum pg_spi_prepare_select_with_cond(PG_FUNCTION_ARGS) {
uint64 proc; uint64 proc;
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
char *query = "SELECT col1 FROM joseph_test.Y WHERE col1 = $1"; char *query = "SELECT col1 FROM Y WHERE col1 = $1";
int result = 0; int result = 0;
ret = SPI_connect(); ret = SPI_connect();
@ -461,7 +461,7 @@ pg_spi_prepare_select_with_cond_without_saveplan (PG_FUNCTION_ARGS)
uint64 proc; uint64 proc;
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
char *query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1"; char *query = "SELECT col1 FROM Y WHERE col2 = $1";
int result = 0; int result = 0;
ret = SPI_connect (); ret = SPI_connect ();
@ -519,7 +519,7 @@ pg_spi_update_y (PG_FUNCTION_ARGS)
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
Datum values[1]; Datum values[1];
char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; const char *query = "UPDATE Y SET col1 = 4 WHERE (col2 = $1)";
ret = SPI_connect (); ret = SPI_connect ();
if (ret != SPI_OK_CONNECT) if (ret != SPI_OK_CONNECT)
@ -552,7 +552,7 @@ pg_spi_prepare_update (PG_FUNCTION_ARGS)
int nargs; int nargs;
Oid argtypes[1]; Oid argtypes[1];
Datum values[1]; Datum values[1];
char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)"; const char *query = "UPDATE Y SET col1 = 4 WHERE (col2 = $1)";
ret = SPI_connect (); ret = SPI_connect ();
if (ret != SPI_OK_CONNECT) if (ret != SPI_OK_CONNECT)

View File

@ -1,42 +1,20 @@
DROP TABLE IF EXISTS X;
DROP TABLE joseph_test.X; CREATE TABLE X (
CREATE TABLE joseph_test.X (
a integer a integer
); );
INSERT INTO joseph_test.X (a) VALUES (1), (2), (3), (4), (5), (6), (7); INSERT INTO X (a)
VALUES (1), (2), (3), (4), (5), (6), (7);
DROP TABLE joseph_test.Y;
CREATE TABLE joseph_test.Y (col1 INT, col2 INT);
INSERT INTO joseph_test.Y (col1,col2) VALUES (1,2), (2,0), (0,4), (4,0), (0,6), (6,7), (7,8);
DROP TABLE joseph_test.Z;
CREATE TABLE joseph_test.Z(col1 BYTEA);
DROP TABLE deposits;
/*CREATE TABLE deposits(
deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY
,shard INT8 NOT NULL
,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
,known_coin_id INT8 NOT NULL
,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL
,wallet_timestamp INT8 NOT NULL
,exchange_timestamp INT8 NOT NULL
,refund_deadline INT8 NOT NULL
,wire_deadline INT8 NOT NULL
,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)
,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)
,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)
,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16)
,wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)
,done BOOLEAN NOT NULL DEFAULT FALSE
,policy_blocked BOOLEAN NOT NULL DEFAULT FALSE
,policy_details_serial_id INT8);
*/
--INSERT INTO deposits VALUES ();
DROP TABLE IF EXISTS Y;
CREATE TABLE Y (col1 INT, col2 INT);
INSERT INTO Y (col1,col2)
VALUES (1,2), (2,0), (0,4), (4,0), (0,6), (6,7), (7,8);
DROP TABLE IF EXISTS Z;
CREATE TABLE Z (col1 BYTEA);
DROP TABLE IF EXISTS deposits;
CREATE TABLE deposits( CREATE TABLE deposits(
deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY
,shard INT8 NOT NULL ,shard INT8 NOT NULL
@ -58,79 +36,81 @@ CREATE TABLE deposits(
,policy_details_serial_id INT8); ,policy_details_serial_id INT8);
CREATE OR REPLACE FUNCTION pg_spi_insert_int() DROP FUNCTION IF EXISTS pg_spi_insert_int;
CREATE FUNCTION pg_spi_insert_int()
RETURNS VOID RETURNS VOID
LANGUAGE c COST 100 LANGUAGE c VOLATILE COST 100
AS '$libdir/own_test', 'pg_spi_insert_int'; AS '$libdir/own_test', 'pg_spi_insert_int';
DROP FUNCTION pg_spi_select_from_x();
CREATE OR REPLACE FUNCTION pg_spi_select_from_x() DROP FUNCTION IF EXISTS pg_spi_select_from_x;
CREATE FUNCTION pg_spi_select_from_x()
RETURNS INT8 RETURNS INT8
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_select_from_x'; AS '$libdir/own_test', 'pg_spi_select_from_x';
/*DROP FUNCTION pg_spi_select_pair_from_y(); /*
CREATE OR REPLACE FUNCTION pg_spi_select_pair_from_y() CREATE FUNCTION pg_spi_select_pair_from_y()
RETURNS valuest RETURNS valuest
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_select_pair_from_y'; AS '$libdir/own_test', 'pg_spi_select_pair_from_y';
*/ */
/*CREATE OR REPLACE FUNCTION pg_spi_select_with_cond() /*CREATE FUNCTION pg_spi_select_with_cond()
RETURNS INT8 RETURNS INT8
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_select_with_cond'; AS '$libdir/own_test', 'pg_spi_select_with_cond';
*/ */
DROP FUNCTION pg_spi_update_y();
CREATE OR REPLACE FUNCTION pg_spi_update_y()
RETURNS VOID
LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_update_y';
DROP FUNCTION pg_spi_prepare_example();
CREATE OR REPLACE FUNCTION pg_spi_prepare_example() DROP FUNCTION IF EXISTS pg_spi_update_y;
CREATE FUNCTION pg_spi_update_y()
RETURNS VOID
LANGUAGE c VOLATILE COST 100
AS '$libdir/own_test', 'pg_spi_update_y';
DROP FUNCTION IF EXISTS pg_spi_prepare_example;
CREATE FUNCTION pg_spi_prepare_example()
RETURNS INT8 RETURNS INT8
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_prepare_example'; AS '$libdir/own_test', 'pg_spi_prepare_example';
DROP FUNCTION pg_spi_prepare_example_without_saveplan(); DROP FUNCTION IF EXISTS pg_spi_prepare_example_without_saveplan;
CREATE OR REPLACE FUNCTION pg_spi_prepare_example_without_saveplan() CREATE FUNCTION pg_spi_prepare_example_without_saveplan()
RETURNS INT8 RETURNS INT8
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_prepare_example_without_saveplan'; AS '$libdir/own_test', 'pg_spi_prepare_example_without_saveplan';
CREATE OR REPLACE FUNCTION pg_spi_prepare_insert() DROP FUNCTION IF EXISTS pg_spi_prepare_insert;
CREATE FUNCTION pg_spi_prepare_insert()
RETURNS VOID RETURNS VOID
LANGUAGE c COST 100 LANGUAGE c VOLATILE COST 100
AS '$libdir/own_test', 'pg_spi_prepare_insert'; AS '$libdir/own_test', 'pg_spi_prepare_insert';
CREATE OR REPLACE FUNCTION pg_spi_prepare_insert_without_saveplan() DROP FUNCTION IF EXISTS pg_spi_prepare_insert_without_saveplan;
CREATE FUNCTION pg_spi_prepare_insert_without_saveplan()
RETURNS VOID RETURNS VOID
LANGUAGE c COST 100 LANGUAGE c VOLATILE COST 100
AS '$libdir/own_test', 'pg_spi_prepare_insert_without_saveplan'; AS '$libdir/own_test', 'pg_spi_prepare_insert_without_saveplan';
/*DROP FUNCTION pg_spi_prepare_select_with_cond(); /*
CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond() CREATE FUNCTION pg_spi_prepare_select_with_cond()
RETURNS INT8 RETURNS INT8
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond'; AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond';
*/ */
DROP FUNCTION pg_spi_prepare_select_with_cond_without_saveplan();
CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond_without_saveplan() DROP FUNCTION IF EXISTS pg_spi_prepare_select_with_cond_without_saveplan;
CREATE FUNCTION pg_spi_prepare_select_with_cond_without_saveplan()
RETURNS INT8 RETURNS INT8
LANGUAGE c COST 100 LANGUAGE c COST 100
AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond_without_saveplan'; AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond_without_saveplan';
DROP FUNCTION pg_spi_prepare_update(); DROP FUNCTION IF EXISTS pg_spi_prepare_update;
CREATE OR REPLACE FUNCTION pg_spi_prepare_update() CREATE FUNCTION pg_spi_prepare_update()
RETURNS VOID RETURNS VOID
LANGUAGE c COST 100 LANGUAGE c VOLATILE COST 100
AS '$libdir/own_test', 'pg_spi_prepare_update'; AS '$libdir/own_test', 'pg_spi_prepare_update';
DROP FUNCTION pg_spi_get_dep_ref_fees( DROP FUNCTION IF EXISTS pg_spi_get_dep_ref_fees;
IN in_timestamp INT8 CREATE FUNCTION pg_spi_get_dep_ref_fees(
,IN merchant_pub BYTEA
,IN wire_target_h_payto BYTEA
,IN wtid BYTEA);
CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees(
IN in_timestamp INT8 IN in_timestamp INT8
,IN merchant_pub BYTEA ,IN merchant_pub BYTEA
,IN wire_target_h_payto BYTEA ,IN wire_target_h_payto BYTEA
@ -140,7 +120,8 @@ CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees(
LANGUAGE c VOLATILE COST 100 LANGUAGE c VOLATILE COST 100
AS '$libdir/own_test', 'pg_spi_get_dep_ref_fees'; AS '$libdir/own_test', 'pg_spi_get_dep_ref_fees';
CREATE OR REPLACE FUNCTION update_pg_spi_get_dep_ref_fees( DROP FUNCTION IF EXISTS update_pg_spi_get_dep_ref_fees;
CREATE FUNCTION update_pg_spi_get_dep_ref_fees(
IN in_refund_deadline INT8, IN in_refund_deadline INT8,
IN in_merchant_pub BYTEA, IN in_merchant_pub BYTEA,
IN in_wire_target_h_payto BYTEA IN in_wire_target_h_payto BYTEA
@ -165,43 +146,47 @@ RETURN QUERY
amount_with_fee_frac; amount_with_fee_frac;
END $$; END $$;
CREATE OR REPLACE FUNCTION stored_procedure_update( DROP FUNCTION IF EXISTS stored_procedure_update;
CREATE FUNCTION stored_procedure_update(
IN in_number INT8 IN in_number INT8
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
UPDATE joseph_test.Y UPDATE Y
SET col1 = 4 SET col1 = 4
WHERE col2 = in_number; WHERE col2 = in_number;
END $$; END $$;
CREATE OR REPLACE FUNCTION stored_procedure_select(OUT out_value INT8) DROP FUNCTION IF EXISTS stored_procedure_select;
CREATE FUNCTION stored_procedure_select(OUT out_value INT8)
RETURNS INT8 RETURNS INT8
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
SELECT 1 SELECT 1
INTO out_value INTO out_value
FROM joseph_test.X; FROM X;
RETURN; RETURN;
END $$; END $$;
CREATE OR REPLACE FUNCTION stored_procedure_insert( DROP FUNCTION IF EXISTS stored_procedure_insert;
CREATE FUNCTION stored_procedure_insert(
IN in_number INT8, IN in_number INT8,
OUT out_number INT8) OUT out_number INT8)
RETURNS INT8 RETURNS INT8
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
INSERT INTO joseph_test.X (a) INSERT INTO X (a)
VALUES (in_number) VALUES (in_number)
RETURNING a INTO out_number; RETURNING a INTO out_number;
END $$; END $$;
CREATE OR REPLACE FUNCTION stored_procedure_select_with_cond( DROP FUNCTION IF EXISTS stored_procedure_select_with_cond;
CREATE FUNCTION stored_procedure_select_with_cond(
IN in_number INT8, IN in_number INT8,
OUT out_number INT8 OUT out_number INT8
) )
@ -210,7 +195,7 @@ LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
SELECT col1 INTO out_number SELECT col1 INTO out_number
FROM joseph_test.Y FROM Y
WHERE col2 = in_number; WHERE col2 = in_number;
RETURN; RETURN;
END $$; END $$;