Reputation: 590
I have a table of images and need to use a C image processing library to extract the n most relevant images from it. I try to figure out what parameters will be passed by prototyping the function in SQL (dummy):
CREATE OR REPLACE FUNCTION clusterize(anyarray,integer)
RETURNS TABLE(image bytea) AS $$
SELECT * FROM $1
ORDER BY random()
LIMIT $2
$$ LANGUAGE SQL; -- will be C
WITH subreq AS (
SELECT decode(encode(thumbnail,'escape'), 'base64') "data",
otherfields
FROM images -- which actually is another WITH subrequest ...
)
SELECT clusterize(* FROM subreq,12)
generates a syntax error close to the $1. How to pass "subreq" results to the function ? In this case, does it mean that all images will be loaded in memory before calling the function, or is there an iterator mechanism ?
Is it simpler to decompose in two functions, an "addimage" function to call for each image and then a "clusterize(12)" that would return a table of images ?
Upvotes: 1
Views: 178
Reputation: 8572
Your function takes anyarray
but bytea
isn't an "array" in the usual PG sense. Since the table you're returning is of bytea
, and you're not doing any sort of cast or transformation, is there any reason not to put the actual type as the parameter?
Regardless, if you want to SELECT *
from an array, you need to UNNEST
it to put it into table form.
So, your clusterize
function now looks like this:
CREATE OR REPLACE FUNCTION clusterize(anyarray,integer)
RETURNS TABLE(image bytea) AS $$
SELECT * FROM UNNEST($1)
ORDER BY random()
LIMIT $2
$$ LANGUAGE SQL
Now to create an actual array from the bytea data. There don't appear to be good bytea functions, so a bit of hackery does it:
WITH subreq AS (
SELECT decode(encode(E'Th\\000omas'::bytea, 'escape'), 'escape') d
)
SELECT clusterize(ARRAY_AGG(SUBSTRING(d FROM g FOR 1)), 4)
FROM subreq, generate_series(1, LENGTH(d)) g
Result:
Now if we can change clusterize
to take a bytea
, we can hide that hacky code in there instead:
CREATE OR REPLACE FUNCTION clusterize(bytea,integer)
RETURNS TABLE(image bytea) AS $$
SELECT SUBSTRING($1 FROM g FOR 1)
FROM generate_series(1, LENGTH($1)) g
ORDER BY random()
LIMIT $2
$$ LANGUAGE SQL
WITH subreq AS (
SELECT decode(encode(E'Th\\000omas'::bytea, 'escape'), 'escape') d
)
SELECT clusterize(d, 4)
FROM subreq
Result:
Upvotes: 1