0

This works:

$entriesResult = pg_query_params("
SELECT * FROM crosstab(
    $$
    SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
    FROM   entry     e
    JOIN   field     f USING (section_id)
    LEFT   JOIN data d USING (field_id, entry_id)
    WHERE  e.section_id = 1 AND f.aggregate = 1 AND f.enabled = 1 AND f.deleted = 0
    ORDER  BY 1, 2
    $$
    ,
    $$
    SELECT field_id FROM field WHERE section_id = 1 AND aggregate = 1 AND enabled = 1 AND deleted = 0 ORDER BY rank
    $$
)
AS ct (entry_id int $fieldPrefixString)
ORDER  BY f1->>'value' DESC
", array());

This produces this error: bind message supplies 1 parameters, but prepared statement "" requires 0

$entriesResult = pg_query_params("
SELECT * FROM crosstab(
    $$
    SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
    FROM   entry     e
    JOIN   field     f USING (section_id)
    LEFT   JOIN data d USING (field_id, entry_id)
    WHERE  e.section_id = $1 AND f.aggregate = 1 AND f.enabled = 1 AND f.deleted = 0
    ORDER  BY 1, 2
    $$
    ,
    $$
    SELECT field_id FROM field WHERE section_id = $1 AND aggregate = 1 AND enabled = 1 AND deleted = 0 ORDER BY rank
    $$
)
AS ct (entry_id int $fieldPrefixString)
ORDER  BY f1->>'value' DESC
", array(3));

The difference is I am using the array parameter in the second, non working example. I'm guessing it's related to using crosstab? How can I make this work with pg_query_params?

As a last resort I can use pg_escape_id, but that's not ideal.

1 Answer 1

2

This is not directly related to crosstab, but to $1 not being interpolated inside literal strings. You'd get the same error writing this:

pg_query_params('SELECT $$ $1 $$', array(3));

$N parameters must stand on their own, as if they were expressions.

So it could be written like this instead, still with the $$-style quoting:

$entriesResult = pg_query_params("
SELECT * FROM crosstab(
    $$
    SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
    FROM   entry     e
    JOIN   field     f USING (section_id)
    LEFT   JOIN data d USING (field_id, entry_id)
    WHERE  e.section_id = $$ || cast($1 as text) || $$ AND f.aggregate = 1 AND f.enabled = 1 AND f.deleted = 0
    ORDER  BY 1, 2
    $$
    ,
    $$
    SELECT field_id FROM field WHERE section_id = $$ || cast($1 as text) || $$ AND aggregate = 1 AND enabled = 1 AND deleted = 0 ORDER BY rank
    $$
)
AS ct (entry_id int $fieldPrefixString)
ORDER  BY f1->>'value' DESC
", array(3));

In this version, $1 will be parsed as a parameter at the SQL level. I use the explicit cast cast($1 as text) because it doesn't leave any ambiguity about the parameter becoming a string, no matter what type it was initially.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.