]> git.frustrated-labs.net Git - pg-cowsay.git/commitdiff
init
authorAlexander Goussas <[email protected]>
Mon, 11 Nov 2024 00:41:29 +0000 (19:41 -0500)
committerAlexander Goussas <[email protected]>
Mon, 11 Nov 2024 00:41:29 +0000 (19:41 -0500)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
pgcowsay--0.0.1.sql [new file with mode: 0644]
pgcowsay.c [new file with mode: 0644]
pgcowsay.control [new file with mode: 0644]
test.sql [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..4b9a674
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.so
+testdata
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..48326d7
--- /dev/null
@@ -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 (file)
index 0000000..18916ea
--- /dev/null
@@ -0,0 +1,98 @@
+#include <unistd.h>
+#include <string.h>
+
+#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 (file)
index 0000000..ca99fb2
--- /dev/null
@@ -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 (file)
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');