Improve nbtree unsatisfiable RowCompare detection.
[pgsql.git] / src / test / regress / expected / largeobject_1.out
blob7172ddb39bb293418e209d5c4f2128920520eefb
1 --
2 -- Test large object support
3 --
4 -- directory paths are passed to us in environment variables
5 \getenv abs_srcdir PG_ABS_SRCDIR
6 \getenv abs_builddir PG_ABS_BUILDDIR
7 -- ensure consistent test output regardless of the default bytea format
8 SET bytea_output TO escape;
9 -- Test ALTER LARGE OBJECT OWNER
10 CREATE ROLE regress_lo_user;
11 SELECT lo_create(42);
12  lo_create 
13 -----------
14         42
15 (1 row)
17 ALTER LARGE OBJECT 42 OWNER TO regress_lo_user;
18 -- Test GRANT, COMMENT as non-superuser
19 SET SESSION AUTHORIZATION regress_lo_user;
20 GRANT SELECT ON LARGE OBJECT 42 TO public;
21 COMMENT ON LARGE OBJECT 42 IS 'the ultimate answer';
22 RESET SESSION AUTHORIZATION;
23 -- Test psql's \lo_list et al (we assume no other LOs exist yet)
24 \lo_list
25                Large objects
26  ID |      Owner      |     Description     
27 ----+-----------------+---------------------
28  42 | regress_lo_user | the ultimate answer
29 (1 row)
31 \lo_list+
32                                   Large objects
33  ID |      Owner      |         Access privileges          |     Description     
34 ----+-----------------+------------------------------------+---------------------
35  42 | regress_lo_user | regress_lo_user=rw/regress_lo_user+| the ultimate answer
36     |                 | =r/regress_lo_user                 | 
37 (1 row)
39 \lo_unlink 42
40 \dl
41       Large objects
42  ID | Owner | Description 
43 ----+-------+-------------
44 (0 rows)
46 -- Load a file
47 CREATE TABLE lotest_stash_values (loid oid, fd integer);
48 -- lo_creat(mode integer) returns oid
49 -- The mode arg to lo_creat is unused, some vestigal holdover from ancient times
50 -- returns the large object id
51 INSERT INTO lotest_stash_values (loid) SELECT lo_creat(42);
52 -- NOTE: large objects require transactions
53 BEGIN;
54 -- lo_open(lobjId oid, mode integer) returns integer
55 -- The mode parameter to lo_open uses two constants:
56 --   INV_WRITE = 0x20000
57 --   INV_READ  = 0x40000
58 -- The return value is a file descriptor-like value which remains valid for the
59 -- transaction.
60 UPDATE lotest_stash_values SET fd = lo_open(loid, CAST(x'20000' | x'40000' AS integer));
61 -- loread/lowrite names are wonky, different from other functions which are lo_*
62 -- lowrite(fd integer, data bytea) returns integer
63 -- the integer is the number of bytes written
64 SELECT lowrite(fd, '
65 I wandered lonely as a cloud
66 That floats on high o''er vales and hills,
67 When all at once I saw a crowd,
68 A host, of golden daffodils;
69 Beside the lake, beneath the trees,
70 Fluttering and dancing in the breeze.
72 Continuous as the stars that shine
73 And twinkle on the milky way,
74 They stretched in never-ending line
75 Along the margin of a bay:
76 Ten thousand saw I at a glance,
77 Tossing their heads in sprightly dance.
79 The waves beside them danced; but they
80 Out-did the sparkling waves in glee:
81 A poet could not but be gay,
82 In such a jocund company:
83 I gazed--and gazed--but little thought
84 What wealth the show to me had brought:
86 For oft, when on my couch I lie
87 In vacant or in pensive mood,
88 They flash upon that inward eye
89 Which is the bliss of solitude;
90 And then my heart with pleasure fills,
91 And dances with the daffodils.
93          -- William Wordsworth
94 ') FROM lotest_stash_values;
95  lowrite 
96 ---------
97      848
98 (1 row)
100 -- lo_close(fd integer) returns integer
101 -- return value is 0 for success, or <0 for error (actually only -1, but...)
102 SELECT lo_close(fd) FROM lotest_stash_values;
103  lo_close 
104 ----------
105         0
106 (1 row)
108 END;
109 -- Copy to another large object.
110 -- Note: we intentionally don't remove the object created here;
111 -- it's left behind to help test pg_dump.
112 SELECT lo_from_bytea(0, lo_get(loid)) AS newloid FROM lotest_stash_values
113 \gset
114 -- Add a comment to it, as well, for pg_dump/pg_upgrade testing.
115 COMMENT ON LARGE OBJECT :newloid IS 'I Wandered Lonely as a Cloud';
116 -- Read out a portion
117 BEGIN;
118 UPDATE lotest_stash_values SET fd=lo_open(loid, CAST(x'20000' | x'40000' AS integer));
119 -- lo_lseek(fd integer, offset integer, whence integer) returns integer
120 -- offset is in bytes, whence is one of three values:
121 --  SEEK_SET (= 0) meaning relative to beginning
122 --  SEEK_CUR (= 1) meaning relative to current position
123 --  SEEK_END (= 2) meaning relative to end (offset better be negative)
124 -- returns current position in file
125 SELECT lo_lseek(fd, 104, 0) FROM lotest_stash_values;
126  lo_lseek 
127 ----------
128       104
129 (1 row)
131 -- loread/lowrite names are wonky, different from other functions which are lo_*
132 -- loread(fd integer, len integer) returns bytea
133 SELECT loread(fd, 28) FROM lotest_stash_values;
134             loread            
135 ------------------------------
136  A host, of golden daffodils;
137 (1 row)
139 SELECT lo_lseek(fd, -19, 1) FROM lotest_stash_values;
140  lo_lseek 
141 ----------
142       113
143 (1 row)
145 SELECT lowrite(fd, 'n') FROM lotest_stash_values;
146  lowrite 
147 ---------
148        1
149 (1 row)
151 SELECT lo_tell(fd) FROM lotest_stash_values;
152  lo_tell 
153 ---------
154      114
155 (1 row)
157 SELECT lo_lseek(fd, -744, 2) FROM lotest_stash_values;
158  lo_lseek 
159 ----------
160       104
161 (1 row)
163 SELECT loread(fd, 28) FROM lotest_stash_values;
164             loread            
165 ------------------------------
166  A host, on golden daffodils;
167 (1 row)
169 SELECT lo_close(fd) FROM lotest_stash_values;
170  lo_close 
171 ----------
172         0
173 (1 row)
175 END;
176 -- Test resource management
177 BEGIN;
178 SELECT lo_open(loid, x'40000'::int) from lotest_stash_values;
179  lo_open 
180 ---------
181        0
182 (1 row)
184 ABORT;
185 \set filename :abs_builddir '/results/invalid/path'
186 \set dobody 'DECLARE loid oid; BEGIN '
187 \set dobody :dobody 'SELECT tbl.loid INTO loid FROM lotest_stash_values tbl; '
188 \set dobody :dobody 'PERFORM lo_export(loid, ' :'filename' '); '
189 \set dobody :dobody 'EXCEPTION WHEN UNDEFINED_FILE THEN '
190 \set dobody :dobody 'RAISE NOTICE ''could not open file, as expected''; END'
191 DO :'dobody';
192 NOTICE:  could not open file, as expected
193 -- Test truncation.
194 BEGIN;
195 UPDATE lotest_stash_values SET fd=lo_open(loid, CAST(x'20000' | x'40000' AS integer));
196 SELECT lo_truncate(fd, 11) FROM lotest_stash_values;
197  lo_truncate 
198 -------------
199            0
200 (1 row)
202 SELECT loread(fd, 15) FROM lotest_stash_values;
203      loread     
204 ----------------
205  \012I wandered
206 (1 row)
208 SELECT lo_truncate(fd, 10000) FROM lotest_stash_values;
209  lo_truncate 
210 -------------
211            0
212 (1 row)
214 SELECT loread(fd, 10) FROM lotest_stash_values;
215                   loread                  
216 ------------------------------------------
217  \000\000\000\000\000\000\000\000\000\000
218 (1 row)
220 SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
221  lo_lseek 
222 ----------
223     10000
224 (1 row)
226 SELECT lo_tell(fd) FROM lotest_stash_values;
227  lo_tell 
228 ---------
229    10000
230 (1 row)
232 SELECT lo_truncate(fd, 5000) FROM lotest_stash_values;
233  lo_truncate 
234 -------------
235            0
236 (1 row)
238 SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
239  lo_lseek 
240 ----------
241      5000
242 (1 row)
244 SELECT lo_tell(fd) FROM lotest_stash_values;
245  lo_tell 
246 ---------
247     5000
248 (1 row)
250 SELECT lo_close(fd) FROM lotest_stash_values;
251  lo_close 
252 ----------
253         0
254 (1 row)
256 END;
257 -- Test 64-bit large object functions.
258 BEGIN;
259 UPDATE lotest_stash_values SET fd = lo_open(loid, CAST(x'20000' | x'40000' AS integer));
260 SELECT lo_lseek64(fd, 4294967296, 0) FROM lotest_stash_values;
261  lo_lseek64 
262 ------------
263  4294967296
264 (1 row)
266 SELECT lowrite(fd, 'offset:4GB') FROM lotest_stash_values;
267  lowrite 
268 ---------
269       10
270 (1 row)
272 SELECT lo_tell64(fd) FROM lotest_stash_values;
273  lo_tell64  
274 ------------
275  4294967306
276 (1 row)
278 SELECT lo_lseek64(fd, -10, 1) FROM lotest_stash_values;
279  lo_lseek64 
280 ------------
281  4294967296
282 (1 row)
284 SELECT lo_tell64(fd) FROM lotest_stash_values;
285  lo_tell64  
286 ------------
287  4294967296
288 (1 row)
290 SELECT loread(fd, 10) FROM lotest_stash_values;
291    loread   
292 ------------
293  offset:4GB
294 (1 row)
296 SELECT lo_truncate64(fd, 5000000000) FROM lotest_stash_values;
297  lo_truncate64 
298 ---------------
299              0
300 (1 row)
302 SELECT lo_lseek64(fd, 0, 2) FROM lotest_stash_values;
303  lo_lseek64 
304 ------------
305  5000000000
306 (1 row)
308 SELECT lo_tell64(fd) FROM lotest_stash_values;
309  lo_tell64  
310 ------------
311  5000000000
312 (1 row)
314 SELECT lo_truncate64(fd, 3000000000) FROM lotest_stash_values;
315  lo_truncate64 
316 ---------------
317              0
318 (1 row)
320 SELECT lo_lseek64(fd, 0, 2) FROM lotest_stash_values;
321  lo_lseek64 
322 ------------
323  3000000000
324 (1 row)
326 SELECT lo_tell64(fd) FROM lotest_stash_values;
327  lo_tell64  
328 ------------
329  3000000000
330 (1 row)
332 SELECT lo_close(fd) FROM lotest_stash_values;
333  lo_close 
334 ----------
335         0
336 (1 row)
338 END;
339 -- lo_unlink(lobjId oid) returns integer
340 -- return value appears to always be 1
341 SELECT lo_unlink(loid) from lotest_stash_values;
342  lo_unlink 
343 -----------
344          1
345 (1 row)
347 TRUNCATE lotest_stash_values;
348 \set filename :abs_srcdir '/data/tenk.data'
349 INSERT INTO lotest_stash_values (loid) SELECT lo_import(:'filename');
350 BEGIN;
351 UPDATE lotest_stash_values SET fd=lo_open(loid, CAST(x'20000' | x'40000' AS integer));
352 -- verify length of large object
353 SELECT lo_lseek(fd, 0, 2) FROM lotest_stash_values;
354  lo_lseek 
355 ----------
356    680800
357 (1 row)
359 -- with the default BLCKSZ, LOBLKSIZE = 2048, so this positions us for a block
360 -- edge case
361 SELECT lo_lseek(fd, 2030, 0) FROM lotest_stash_values;
362  lo_lseek 
363 ----------
364      2030
365 (1 row)
367 -- this should get half of the value from page 0 and half from page 1 of the
368 -- large object
369 SELECT loread(fd, 36) FROM lotest_stash_values;
370                             loread                            
371 --------------------------------------------------------------
372  44\011144\0111144\0114144\0119144\01188\01189\011SNAAAA\011F
373 (1 row)
375 SELECT lo_tell(fd) FROM lotest_stash_values;
376  lo_tell 
377 ---------
378     2066
379 (1 row)
381 SELECT lo_lseek(fd, -26, 1) FROM lotest_stash_values;
382  lo_lseek 
383 ----------
384      2040
385 (1 row)
387 SELECT lowrite(fd, 'abcdefghijklmnop') FROM lotest_stash_values;
388  lowrite 
389 ---------
390       16
391 (1 row)
393 SELECT lo_lseek(fd, 2030, 0) FROM lotest_stash_values;
394  lo_lseek 
395 ----------
396      2030
397 (1 row)
399 SELECT loread(fd, 36) FROM lotest_stash_values;
400                       loread                      
401 --------------------------------------------------
402  44\011144\011114abcdefghijklmnop9\011SNAAAA\011F
403 (1 row)
405 SELECT lo_close(fd) FROM lotest_stash_values;
406  lo_close 
407 ----------
408         0
409 (1 row)
411 END;
412 \set filename :abs_builddir '/results/lotest.txt'
413 SELECT lo_export(loid, :'filename') FROM lotest_stash_values;
414  lo_export 
415 -----------
416          1
417 (1 row)
419 \lo_import :filename
420 \set newloid :LASTOID
421 -- just make sure \lo_export does not barf
422 \set filename :abs_builddir '/results/lotest2.txt'
423 \lo_export :newloid :filename
424 -- This is a hack to test that export/import are reversible
425 -- This uses knowledge about the inner workings of large object mechanism
426 -- which should not be used outside it.  This makes it a HACK
427 SELECT pageno, data FROM pg_largeobject WHERE loid = (SELECT loid from lotest_stash_values)
428 EXCEPT
429 SELECT pageno, data FROM pg_largeobject WHERE loid = :newloid;
430  pageno | data 
431 --------+------
432 (0 rows)
434 SELECT lo_unlink(loid) FROM lotest_stash_values;
435  lo_unlink 
436 -----------
437          1
438 (1 row)
440 TRUNCATE lotest_stash_values;
441 \lo_unlink :newloid
442 \set filename :abs_builddir '/results/lotest.txt'
443 \lo_import :filename
444 \set newloid_1 :LASTOID
445 SELECT lo_from_bytea(0, lo_get(:newloid_1)) AS newloid_2
446 \gset
447 SELECT fipshash(lo_get(:newloid_1)) = fipshash(lo_get(:newloid_2));
448  ?column? 
449 ----------
451 (1 row)
453 SELECT lo_get(:newloid_1, 0, 20);
454                   lo_get                   
455 -------------------------------------------
456  8800\0110\0110\0110\0110\0110\0110\011800
457 (1 row)
459 SELECT lo_get(:newloid_1, 10, 20);
460                   lo_get                   
461 -------------------------------------------
462  \0110\0110\0110\011800\011800\0113800\011
463 (1 row)
465 SELECT lo_put(:newloid_1, 5, decode('afafafaf', 'hex'));
466  lo_put 
467 --------
469 (1 row)
471 SELECT lo_get(:newloid_1, 0, 20);
472                      lo_get                      
473 -------------------------------------------------
474  8800\011\257\257\257\2570\0110\0110\0110\011800
475 (1 row)
477 SELECT lo_put(:newloid_1, 4294967310, 'foo');
478  lo_put 
479 --------
481 (1 row)
483 SELECT lo_get(:newloid_1);
484 ERROR:  large object read request is too large
485 SELECT lo_get(:newloid_1, 4294967294, 100);
486                                lo_get                                
487 ---------------------------------------------------------------------
488  \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000foo
489 (1 row)
491 \lo_unlink :newloid_1
492 \lo_unlink :newloid_2
493 -- This object is left in the database for pg_dump test purposes
494 SELECT lo_from_bytea(0, E'\\xdeadbeef') AS newloid
495 \gset
496 SET bytea_output TO hex;
497 SELECT lo_get(:newloid);
498    lo_get   
499 ------------
500  \xdeadbeef
501 (1 row)
503 -- Create one more object that we leave behind for testing pg_dump/pg_upgrade;
504 -- this one intentionally has an OID in the system range
505 SELECT lo_create(2121);
506  lo_create 
507 -----------
508       2121
509 (1 row)
511 COMMENT ON LARGE OBJECT 2121 IS 'testing comments';
512 -- Test writes on large objects in read-only transactions
513 START TRANSACTION READ ONLY;
514 -- INV_READ ... ok
515 SELECT lo_open(2121, x'40000'::int);
516  lo_open 
517 ---------
518        0
519 (1 row)
521 -- INV_WRITE ... error
522 SELECT lo_open(2121, x'20000'::int);
523 ERROR:  cannot execute lo_open(INV_WRITE) in a read-only transaction
524 ROLLBACK;
525 START TRANSACTION READ ONLY;
526 SELECT lo_create(42);
527 ERROR:  cannot execute lo_create() in a read-only transaction
528 ROLLBACK;
529 START TRANSACTION READ ONLY;
530 SELECT lo_creat(42);
531 ERROR:  cannot execute lo_creat() in a read-only transaction
532 ROLLBACK;
533 START TRANSACTION READ ONLY;
534 SELECT lo_unlink(42);
535 ERROR:  cannot execute lo_unlink() in a read-only transaction
536 ROLLBACK;
537 START TRANSACTION READ ONLY;
538 SELECT lowrite(42, 'x');
539 ERROR:  cannot execute lowrite() in a read-only transaction
540 ROLLBACK;
541 START TRANSACTION READ ONLY;
542 SELECT lo_import(:'filename');
543 ERROR:  cannot execute lo_import() in a read-only transaction
544 ROLLBACK;
545 START TRANSACTION READ ONLY;
546 SELECT lo_truncate(42, 0);
547 ERROR:  cannot execute lo_truncate() in a read-only transaction
548 ROLLBACK;
549 START TRANSACTION READ ONLY;
550 SELECT lo_truncate64(42, 0);
551 ERROR:  cannot execute lo_truncate64() in a read-only transaction
552 ROLLBACK;
553 START TRANSACTION READ ONLY;
554 SELECT lo_from_bytea(0, 'x');
555 ERROR:  cannot execute lo_from_bytea() in a read-only transaction
556 ROLLBACK;
557 START TRANSACTION READ ONLY;
558 SELECT lo_put(42, 0, 'x');
559 ERROR:  cannot execute lo_put() in a read-only transaction
560 ROLLBACK;
561 -- Clean up
562 DROP TABLE lotest_stash_values;
563 DROP ROLE regress_lo_user;