diff --git a/frameworks/Haskell/postgrest/README.md b/frameworks/Haskell/postgrest/README.md old mode 100755 new mode 100644 index 385ebf7b6ab..90dd62acf81 --- a/frameworks/Haskell/postgrest/README.md +++ b/frameworks/Haskell/postgrest/README.md @@ -7,7 +7,7 @@ * [DB](src/db.sql) * [QUERY](src/query.sql) * [CACHED QUERY] Not Implemented -* [UPDATE] Not Implemented +* [UPDATE](src/update.sql) * [FORTUNES](src/fortunes.sql) ## Important Libraries @@ -17,7 +17,7 @@ The tests were run with: ## Test URLs ### JSON -http://localhost:3000/rpc/json +http://localhost:3000/rpc/jsonser ### PLAINTEXT @@ -31,13 +31,20 @@ http://localhost:3000/rpc/db http://localhost:3000/rpc/query?queries= -### CACHED QUERY Not Implemented +### CACHED QUERY - Not Implemented http://localhost:8080/cached_query?queries= -### UPDATE Not Implemented +### UPDATE - Not Working -http://localhost:3000/rpc/update?queries= +http://localhost:3000/rpc/updates?queries= + +Technically, this is implemented (maybe not correctly though). +However, the benchmark issues this as a GET request. +PostgREST sets the transaction to READ ONLY for GET requests, +as they are supposed to be idempotent. +Hence this results in an error. Calling the endpoint with POST +works though. ### FORTUNES diff --git a/frameworks/Haskell/postgrest/benchmark_config.json b/frameworks/Haskell/postgrest/benchmark_config.json index be82b4771a8..228ee2f5be0 100755 --- a/frameworks/Haskell/postgrest/benchmark_config.json +++ b/frameworks/Haskell/postgrest/benchmark_config.json @@ -3,11 +3,11 @@ "tests": [ { "default": { - "json_url": "/rpc/json", + "json_url": "/rpc/jsonser", "plaintext_url": "/rpc/plaintext", "db_url": "/rpc/db", "query_url": "/rpc/queries?queries=", - "fortunes_url": "/rpc/fortunes.html", + "fortune_url": "/rpc/fortunes", "port": 3000, "approach": "Realistic", "classification": "Micro", diff --git a/frameworks/Haskell/postgrest/config.toml b/frameworks/Haskell/postgrest/config.toml index b98dcecc8ed..a5606004603 100644 --- a/frameworks/Haskell/postgrest/config.toml +++ b/frameworks/Haskell/postgrest/config.toml @@ -6,6 +6,7 @@ urls.plaintext = "/rpc/plaintext" urls.json = "/rpc/json" urls.db = "/rpc/db" urls.query = "/rpc/queries?queries=" +urls.fortune = "/rpc/fortunes" approach = "Realistic" classification = "Micro" database = "postgres" diff --git a/frameworks/Haskell/postgrest/docker-compose.yml b/frameworks/Haskell/postgrest/docker-compose.yml index 8b8b2a03e0f..eca0e4bbfb8 100644 --- a/frameworks/Haskell/postgrest/docker-compose.yml +++ b/frameworks/Haskell/postgrest/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3' services: tfb-database: build: @@ -13,4 +12,6 @@ services: dockerfile: postgrest.dockerfile context: . ports: - - 3030:3000 \ No newline at end of file + - 3030:3000 + depends_on: + - tfb-database diff --git a/frameworks/Haskell/postgrest/postgrest.conf b/frameworks/Haskell/postgrest/postgrest.conf index 688ef63d886..eaf7acfddac 100644 --- a/frameworks/Haskell/postgrest/postgrest.conf +++ b/frameworks/Haskell/postgrest/postgrest.conf @@ -16,4 +16,3 @@ role-claim-key = "$(PGRST_ROLE_CLAIM_KEY)" max-rows = "$(PGRST_MAX_ROWS)" pre-request = "$(PGRST_PRE_REQUEST)" root-spec = "$(PGRST_ROOT_SPEC)" -raw-media-types = "$(PGRST_RAW_MEDIA_TYPES)" \ No newline at end of file diff --git a/frameworks/Haskell/postgrest/postgrest.dockerfile b/frameworks/Haskell/postgrest/postgrest.dockerfile index fb5f224e9bd..fb25374ce37 100644 --- a/frameworks/Haskell/postgrest/postgrest.dockerfile +++ b/frameworks/Haskell/postgrest/postgrest.dockerfile @@ -23,12 +23,10 @@ ENV PGRST_MAX_ROWS= ENV PGRST_PRE_REQUEST= ENV PGRST_ROLE_CLAIM_KEY=.role ENV PGRST_ROOT_SPEC= -ENV PGRST_RAW_MEDIA_TYPES= ENV PGRST_DB_URI=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world ENV PGRST_DB_SCHEMA=public ENV PGRST_DB_ANON_ROLE=benchmarkdbuser -ENV PGRST_RAW_MEDIA_TYPES="text/html, text/plain" ENV PGRST_DB_POOL=64 RUN mkdir /app COPY src /app @@ -37,4 +35,4 @@ WORKDIR /app EXPOSE 3000 -ENTRYPOINT [ "/app/entrypoint.sh" ] \ No newline at end of file +ENTRYPOINT [ "/app/entrypoint.sh" ] diff --git a/frameworks/Haskell/postgrest/src/fortunes.sql b/frameworks/Haskell/postgrest/src/fortunes.sql index 5d4444b9529..f8de4591c8c 100644 --- a/frameworks/Haskell/postgrest/src/fortunes.sql +++ b/frameworks/Haskell/postgrest/src/fortunes.sql @@ -1,35 +1,20 @@ -CREATE TYPE fortune_t AS (id int, message text); +create domain "text/html" as text; -create or replace function fortune_template(f fortune_t) returns text as $$ - SELECT format('%s%s', $1.id, regexp_replace($1.message, '<', '<','g')); -$$ language sql volatile; +create or replace function sanitize_html(text) returns text as $$ + select replace(replace(replace(replace(replace($1, '&', '&'), '"', '"'),'>', '>'),'<', '<'), '''', ''') +$$ language sql immutable; -create or replace function fortunes_template(fortunes fortune_t[]) returns text as $$ -WITH header AS ( - SELECT 0 as id,' -Fortunes' as html -), footer AS ( - SELECT 2,'
idmessage
' as html -), fortunes AS ( - SELECT unnest as fortune from unnest($1) -), additional AS ( - SELECT (-1, 'Additional fortune added at request time.')::fortune_t as f -), all_fortunes AS ( - SELECT * from (SELECT * FROM fortunes UNION ALL SELECT * from additional) p ORDER BY (fortune).message -), fortunes_html AS ( - SELECT 1,string_agg(fortune_template(fortune), '') from all_fortunes -), html AS ( - SELECT * FROM header UNION SELECT * FROM fortunes_html UNION SELECT * from footer ORDER BY id -) -SELECT string_agg(html,'') from html; -$$ language sql volatile; +create or replace function fortune_template("Fortune") returns text as $$ + SELECT format('%s%s', $1.id, sanitize_html($1.message)); +$$ language sql immutable; -create or replace function "fortunes.html"() returns bytea as $$ -DECLARE - fortunes fortune_t[]; -BEGIN - SET LOCAL "response.headers" = '[{"Content-Type": "text/html"}]'; - SELECT array_agg(CAST((id,message) AS fortune_t)) FROM "Fortunes" INTO fortunes; - RETURN convert_to(fortunes_template(fortunes), 'UTF8'); -END -$$ language plpgsql volatile; +create or replace function fortunes() returns "text/html" as $$ + -- This is only necessary bc. of the benchmark: The domain gives us content-type: text/html, + -- but the benchmark explicitly tests for the charset in the content-type. + select set_config('response.headers', '[{"Content-Type": "text/html; charset=utf-8"}]', true); + + select 'Fortunes' + || string_agg(fortune_template(f), NULL order by f.message collate unicode asc) + || '
idmessage
' + from (select * from "Fortune" union all select 0, 'Additional fortune added at request time.') f; +$$ language sql volatile; diff --git a/frameworks/Haskell/postgrest/src/json.sql b/frameworks/Haskell/postgrest/src/json.sql index 69f468887f8..5df9168e372 100644 --- a/frameworks/Haskell/postgrest/src/json.sql +++ b/frameworks/Haskell/postgrest/src/json.sql @@ -1,3 +1,3 @@ -create function json() returns json as $$ +create function jsonser() returns json as $$ SELECT json_build_object('message', 'Hello, World!'); -$$ language sql volatile; \ No newline at end of file +$$ language sql immutable; diff --git a/frameworks/Haskell/postgrest/src/plaintext.sql b/frameworks/Haskell/postgrest/src/plaintext.sql index ed9dbda1784..b5be0003fcc 100644 --- a/frameworks/Haskell/postgrest/src/plaintext.sql +++ b/frameworks/Haskell/postgrest/src/plaintext.sql @@ -1,3 +1,5 @@ -create function plaintext() returns text as $$ +create domain "text/plain" as text; + +create function plaintext() returns "text/plain" as $$ SELECT 'Hello, World!'; -$$ language sql volatile; \ No newline at end of file +$$ language sql immutable; diff --git a/frameworks/Haskell/postgrest/src/update.sql b/frameworks/Haskell/postgrest/src/update.sql index 541e2a507cc..71aededfe44 100644 --- a/frameworks/Haskell/postgrest/src/update.sql +++ b/frameworks/Haskell/postgrest/src/update.sql @@ -1,4 +1,4 @@ -create or replace function update(queries text default '') returns jsonb as $$ +create or replace function updates(queries text default '') returns jsonb as $$ DECLARE r "World"%ROWTYPE; j jsonb := jsonb_build_array(); @@ -6,11 +6,10 @@ DECLARE rnd_id int; count int; BEGIN - SET TRANSACTION READ WRITE; IF queries ~ '^[1-9]\d{0,2}$' THEN count := CAST(queries as int); - ELSE - count := 1; + ELSE + count := 1; END IF; IF count > 500 THEN count := 500;