7

In PostgreSQL 9.0 I have this PLPGSQL anonymous code block:

DO $$
    DECLARE
        bigobject integer;
    BEGIN
        SELECT lo_creat(-1) INTO bigobject;
        ALTER LARGE OBJECT bigobject OWNER TO postgres;
        INSERT INTO files (id, "mountPoint", data, comment) VALUES (15, '/images/image.png', bigobject, 'image data');
        SET search_path = pg_catalog;
        SELECT pg_catalog.lo_open(bigobject, 131072);
        SELECT pg_catalog.lowrite(0, '\\x000001000100101010000000000028010000160000002800000010000000200000000100040');
        SELECT pg_catalog.lo_close(0);
        REVOKE ALL ON LARGE OBJECT bigobject FROM PUBLIC;
        REVOKE ALL ON LARGE OBJECT bigobject FROM postgres;
        GRANT ALL ON LARGE OBJECT bigobject TO postgres;
        GRANT ALL ON LARGE OBJECT bigobject TO "com.ektyn.eshops.myuser";
    END
$$;

but it fails:

ERROR:  syntax error at or near "bigobject"
LINE 6:   ALTER LARGE OBJECT bigobject OWNER TO postgres;
                             ^

********** Error **********

ERROR: syntax error at or near "bigobject"
SQL state: 42601
Character: 103

and I can't find mistake in code.

Milen A. Radev
  • 60,241
  • 22
  • 105
  • 110
1ac0
  • 2,875
  • 3
  • 33
  • 47

3 Answers3

7

There must be an oid constant in ALTER LARGE OBJECT oid .... Try this workaround:

DO $$
    DECLARE
        bigobject integer;
    BEGIN
        SELECT lo_creat(-1) INTO bigobject;
        EXECUTE 'ALTER LARGE OBJECT ' || bigobject::text || ' OWNER TO postgres';
        ...

The same also applies to GRANT and REVOKE, of course.

klin
  • 112,967
  • 15
  • 204
  • 232
6

In addition to what @klin already cleared up, you cannot use SELECT without a target in PL/pgSQL code. Replace it with PERFORM in those calls.

Aside: Using "com.ektyn.eshops.myuser" as name for a role is a terrible idea. Use legal, lower case identifiers that don't have to be double-quoted.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
5

This is an artifact of the fact that PostgreSQL has two completely different kinds of SQL statements internally - plannable (SELECT, INSERT, UPDATE, and DELETE) and unplannable (everything else) statements.

Only plannable statements support query parameters.

PL/pgSQL implements variable substitutions into statements, like your bigobject, using query parameters.

Because they aren't supported for non-plannable statements, no substitution is performed. So PL/pgSQL tries to execute the statement literally, as if you'd typed:

ALTER LARGE OBJECT bigobject OWNER TO postgres;

directly at the psql prompt. It does not detect this as an error.

To work around this, use EXECUTE ... FORMAT, e.g.

EXECUTE format('ALTER LARGE OBJECT %s OWNER TO postgres', bigobject);

See this related answer about COPY.

Community
  • 1
  • 1
Craig Ringer
  • 307,061
  • 76
  • 688
  • 778