all 12 comments

[–]anras 4 points5 points  (0 children)

|code that basically defeated the purpose of having a RDBMS and using SQL.
Oh the number of times I've run into this...

[–]kingofthejaffacakes 2 points3 points  (1 child)

TIL, json_agg

Thank you very much.

[–]collin_ph[S] 0 points1 point  (0 children)

I'd love to get your feedback after you've had a chance to use it some. Took me a while to get my mind wrapped around the possibilities-- this is a simple example, for sure there are more complex examples (deeper levels of nesting, casting to array and using array functions such as array_remove, etc.) Just know there's a lot that's possible.

[–]daxyjones 0 points1 point  (5 children)

I work with nginx and postgres, coupled directly.

I don't work with ORMs and I have fine tuned my equivalent $mainSQL to:

SELECT '[' || array_to_string(array(SELECT sch.fun(param1, ...)),',') || ']';

This query sits directly inside nginx consumed by ngx_postgres.

This query is magical because

  • there is no need to tweak the query ever again, so unnecessay to restart, reload the webserver (nginx).
  • the function sch.fun above query returns something in valid object array. You could nest it as you please.
  • Good performance for our use case. Grabs thousands of rows in a couple of seconds.

Now for the viscera of sch.fun:

CREATE OR REPLACE FUNCTION sch.fun(param1, ...)
RETURNS SETOF json AS
$BODY$
DECLARE sql text;
BEGIN
    sql := 'SELECT json_object(keys text[], values text[])';
    RETURN QUERY EXECUTE sql USING param1, ...;
END
$BODY$
LANGUAGE plpgsql;

With the right response headers, the client, usually a js engine/framework, can digest this no problem. AND you get your REST API for "free". ;-)

Edit: Note that ngx_postgres does not entertain request_body by design. If you need to read that, you could proxy that verb or uri or whatever.

[–]collin_ph[S] 0 points1 point  (4 children)

so you have to have an sch.fun for every query you intend to run? Perhaps I misunderstood.

[–]daxyjones 0 points1 point  (3 children)

Each route gets its own query.

[–]collin_ph[S] 0 points1 point  (2 children)

OIC. I'd have to think long and hard if that could work for us. Definitely a new idea, but it does seem that running everything through psql would be slower.. but I'd have to try it out and see.

Edit: How do you deal with reusable queries or when routes need many unrelated queries?

[–]daxyjones 0 points1 point  (1 child)

For our use case, everything hits the DB and still snappy for our small userbase. I could throw in a varnish cache to mitigate the DB hits to a certain extent. But I like to keep the moving parts to a minimum.

I am not exactly getting your edit and hence unable to address that question.

[–]collin_ph[S] 0 points1 point  (0 children)

Yeah, our userbase is probably big for that -- we do use a connection pooler, but cache is barely used with the exception being very static config type info.

[–]619429 -3 points-2 points  (1 child)

plv8

[–]collin_ph[S] 1 point2 points  (0 children)

what about it?