From 818a1e4844b3340e3105a1c45c21f8aeecaee879 Mon Sep 17 00:00:00 2001 From: Alexander Goussas Date: Sun, 10 Nov 2024 19:41:29 -0500 Subject: [PATCH 1/1] init --- .gitignore | 3 ++ Makefile | 7 ++++ pgcowsay--0.0.1.sql | 9 +++++ pgcowsay.c | 98 +++++++++++++++++++++++++++++++++++++++++++++ pgcowsay.control | 3 ++ test.sql | 4 ++ 6 files changed, 124 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 pgcowsay--0.0.1.sql create mode 100644 pgcowsay.c create mode 100644 pgcowsay.control create mode 100644 test.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b9a674 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +*.so +testdata diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bf7355c --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +MODULES = pgcowsay +EXTENSION = pgcowsay +DATA = pgcowsay--0.0.1.sql + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) diff --git a/pgcowsay--0.0.1.sql b/pgcowsay--0.0.1.sql new file mode 100644 index 0000000..48326d7 --- /dev/null +++ b/pgcowsay--0.0.1.sql @@ -0,0 +1,9 @@ +-- pgweb--0.0.1.sql + +create schema pgcowsay; + +create or replace function pgcowsay.say(TEXT) +returns text as 'pgcowsay', 'pgcowsay_say' +language c strict; + +grant execute on function pgcowsay.say(TEXT) to public; diff --git a/pgcowsay.c b/pgcowsay.c new file mode 100644 index 0000000..18916ea --- /dev/null +++ b/pgcowsay.c @@ -0,0 +1,98 @@ +#include +#include + +#include "postgres.h" + +#include "varatt.h" +#include "catalog/pg_type_d.h" +#include "fmgr.h" +#include "nodes/pg_list.h" +#include "parser/parse_func.h" +#include "utils/builtins.h" +#include "utils/datum.h" +#include "utils/json.h" +#include "utils/memutils.h" +#include "utils/regproc.h" + +PG_MODULE_MAGIC; + +static MemoryContext PGCowsayContext = NULL; + + +void _PG_init(void) +{ + PGCowsayContext = AllocSetContextCreate( + TopMemoryContext, + "PGCowsayContext", + ALLOCSET_DEFAULT_SIZES); +} + +PG_FUNCTION_INFO_V1(pgcowsay_say); +Datum pgcowsay_say(PG_FUNCTION_ARGS) +{ + MemoryContext oldctx; + char *message; + char *program; + char *command; + FILE *pipe; + char buffer[4096]; + char *output; + size_t output_len; + text *result; + int success; + size_t program_len; + size_t message_len; + size_t command_len; + + oldctx = MemoryContextSwitchTo(PGCowsayContext); + + program = "cowsay"; + program_len = strlen(program); + + message = TextDatumGetCString(PG_GETARG_DATUM(0)); + message_len = strlen(message); + + command = palloc(program_len + message_len + 2); + command_len = program_len + message_len + 2; + + memset(command, 0, command_len); + memcpy(command, program, program_len); + memcpy(command + program_len, " ", 1); + memcpy(command + program_len + 1, message, message_len); + + success = 1; + + pipe = popen(command, "r"); + if (pipe == NULL) { + success = 0; + goto exit; + } + + output = palloc(1); + output_len = 0; + + while (fgets(buffer, sizeof(buffer), pipe) != NULL) { + size_t read = strlen(buffer); + output = repalloc(output, output_len + read + 1); + memcpy(output + output_len, buffer, read); + output_len += read; + } + + output[output_len] = '\0'; + pclose(pipe); + + result = cstring_to_text(output); + +exit: + + MemoryContextSwitchTo(oldctx); + + if (success) { + PG_RETURN_TEXT_P(result); + } else { + result = cstring_to_text("no cows"); + PG_RETURN_TEXT_P(result); + } + + MemoryContextReset(PGCowsayContext); +} diff --git a/pgcowsay.control b/pgcowsay.control new file mode 100644 index 0000000..ca99fb2 --- /dev/null +++ b/pgcowsay.control @@ -0,0 +1,3 @@ +default_version = '0.0.1' +module_pathname = '$libdir/pgcowsay' +relocatable = true diff --git a/test.sql b/test.sql new file mode 100644 index 0000000..782c459 --- /dev/null +++ b/test.sql @@ -0,0 +1,4 @@ +drop extension if exists pgcowsay; +create extension pgcowsay; + +select pgcowsay.say('hello world'); -- 2.43.0