forked from apache/cloudberry
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexternal_table.source
More file actions
3705 lines (3501 loc) · 110 KB
/
external_table.source
File metadata and controls
3705 lines (3501 loc) · 110 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--
-- external tables - short and simple functional tests.
--
-- start_matchsubs
--
-- # replace return code in error message (platform specific)
--
-- m/ERROR\:\s+external table .* command ended with .* not found/
-- s/nosuchcommand\:\s*(command)? not found/nosuchcommand\: NOT FOUND/
--
-- m/ERROR\:\s+external table .* command ended with .*No such file.*/
-- s/nosuchfile\.txt\:\s*No such file (or directory)?/nosuchfile\.txt\: NO SUCH FILE/
-- m/ERROR\:\s+external table .* command ended with .*No such file.*/i
-- s/cat\: (cannot open)? nosuchfile\.txt/cat\: nosuchfile\.txt/
--
-- # remove line number - redhat
-- m/ERROR\:\s+external table .* command ended with .*NOT FOUND.*/i
-- s/\s+line \d+\://
-- # remove line number - Debian
-- m/ERROR\:\s+external table .* command ended with .*sh: 1: .*NOT FOUND.*/i
-- s/ sh: 1: / sh: /
--
-- m/DETAIL: Found \d+ URLs and \d+ primary segments./
-- s/Found.+//
--
-- end_matchsubs
CREATE TABLE REG_REGION (R_REGIONKEY INT, R_NAME CHAR(25), R_COMMENT VARCHAR(152)) DISTRIBUTED BY (R_REGIONKEY);
-- --------------------------------------
-- 'file' protocol - (only CREATE, don't SELECT - won't work on distributed installation)
-- --------------------------------------
CREATE EXTERNAL TABLE EXT_NATION ( N_NATIONKEY INTEGER ,
N_NAME CHAR(25) ,
N_REGIONKEY INTEGER ,
N_COMMENT VARCHAR(152))
location ('file://@hostname@@abs_srcdir@/data/nation.tbl' )
FORMAT 'text' (delimiter '|');
CREATE EXTERNAL TABLE EXT_REGION (LIKE REG_REGION)
location ('file://@hostname@@abs_srcdir@/data/region.tbl' )
FORMAT 'text' (delimiter '|');
-- Only tables with custom protocol should create dependency, due to a bug there
-- used to be entries created for non custom protocol tables with refobjid=0.
SELECT * FROM pg_depend WHERE refclassid = 'pg_extprotocol'::regclass and refobjid = 0;
-- drop tables
DROP EXTERNAL TABLE EXT_NATION;
DROP EXTERNAL TABLE EXT_REGION;
-- start_ignore
-- --------------------------------------
-- check platform
-- --------------------------------------
DROP TABLE IF EXISTS REG_REGION;
DROP TABLE IF EXISTS tableless_heap;
DROP TABLE IF EXISTS errlog_save;
DROP TABLE IF EXISTS exttab_insert_1;
DROP TABLE IF EXISTS exttab_ctas_1;
DROP TABLE IF EXISTS exttab_constraints_insert_1;
DROP EXTERNAL TABLE IF EXISTS tableless_ext;
DROP EXTERNAL TABLE IF EXISTS ret_too_many_uris;
DROP EXTERNAL TABLE IF EXISTS wet_too_many_uris;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_1;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_error_1;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_2;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_3;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_4;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_5;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_6;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_7;
DROP EXTERNAL TABLE IF EXISTS exttab_constraints_1;
DROP EXTERNAL TABLE IF EXISTS exttab_cte_1;
DROP EXTERNAL TABLE IF EXISTS exttab_cte_2;
DROP EXTERNAL TABLE IF EXISTS exttab_permissions_1;
DROP EXTERNAL TABLE IF EXISTS exttab_permissions_2;
DROP EXTERNAL TABLE IF EXISTS exttab_permissions_3;
DROP EXTERNAL TABLE IF EXISTS exttab_subq_1;
DROP EXTERNAL TABLE IF EXISTS exttab_subq_2;
DROP EXTERNAL TABLE IF EXISTS exttab_subtxs_1;
DROP EXTERNAL TABLE IF EXISTS exttab_subtxs_2;
DROP EXTERNAL TABLE IF EXISTS exttab_txs_1;
DROP EXTERNAL TABLE IF EXISTS exttab_txs_2;
DROP EXTERNAL TABLE IF EXISTS exttab_udfs_1;
DROP EXTERNAL TABLE IF EXISTS exttab_udfs_2;
DROP EXTERNAL TABLE IF EXISTS exttab_views_3;
DROP EXTERNAL WEB TABLE IF EXISTS table_env;
DROP EXTERNAL WEB TABLE IF EXISTS table_master;
DROP EXTERNAL WEB TABLE IF EXISTS table_qry;
DROP VIEW IF EXISTS exttab_views_3;
DROP PROTOCOL IF EXISTS demoprot_untrusted;
DROP PROTOCOL IF EXISTS demoprot_untrusted2;
drop external web table if exists check_ps;
CREATE EXTERNAL WEB TABLE check_ps (x text)
execute E'( (ps -ef || ps -aux) | grep gpfdist | grep -v grep)'
on SEGMENT 0
format 'text';
drop external web table if exists check_env;
CREATE EXTERNAL WEB TABLE check_env (x text)
execute E'( env | sort)'
on SEGMENT 0
format 'text';
select * from check_ps;
select * from check_env;
drop external table check_ps;
drop external table check_env;
-- end_ignore
-- table to get shell command "env" output which list all environment variable
CREATE EXTERNAL WEB TABLE table_env (val TEXT)
EXECUTE E'env' ON SEGMENT 0
FORMAT 'TEXT' (ESCAPE 'OFF');
SELECT * FROM table_env WHERE val LIKE 'GP_QUERY%' ORDER BY val ASC;
SELECT * FROM table_env WHERE val LIKE 'GP_QUERY%\%' ESCAPE '&' ORDER BY val ASC;
-- ensure squelching on master
CREATE EXTERNAL WEB TABLE table_master (val TEXT)
EXECUTE E'cat @abs_srcdir@/data/lineitem.csv' ON MASTER
FORMAT 'TEXT' (ESCAPE 'OFF');
BEGIN;
DECLARE _psql_cursor NO SCROLL CURSOR FOR SELECT 1 FROM table_master;
FETCH FORWARD 1 FROM _psql_cursor;
CLOSE _psql_cursor;
COMMIT;
-- echo will behave differently on different platforms, force to use bash with -E option
CREATE EXTERNAL WEB TABLE table_qry (val TEXT)
EXECUTE E'/usr/bin/env bash -c ''echo -E "$GP_QUERY_STRING"''' ON SEGMENT 0
FORMAT 'TEXT' (ESCAPE 'OFF');
SELECT * FROM table_qry WHERE val LIKE '%\\%' ORDER BY val ASC;
SELECT * FROM table_qry WHERE val LIKE '%\%' ESCAPE '&' ORDER BY val ASC;
-- --------------------------------------
-- some negative tests
-- --------------------------------------
--
-- test for exec child process stderr showing in error message
--
create external web table ext_stderr1(a text) execute 'nosuchcommand' format 'text';
create external web table ext_stderr2(a text) execute 'cat nosuchfile.txt' format 'text';
select * from ext_stderr1;
select * from ext_stderr2;
drop external web table ext_stderr1;
drop external web table ext_stderr2;
--
-- bad csv (quote must be a single char)
--
create external table bad_whois (
source_lineno int,
domain_name varchar(350)
)
location ('gpfdist://@hostname@:7070/exttab1/whois.csv' )
format 'csv' ( header quote as 'ggg');
select count(*) from bad_whois;
drop external table bad_whois;
--
-- try a bad location
--
create external table badt1 (x text)
location ('file://@hostname@@abs_srcdir@/data/no/such/place/badt1.tbl' )
format 'text' (delimiter '|');
select * from badt1;
drop external table badt1;
--
-- try a bad protocol
--
create external table badt2 (x text)
location ('bad_protocol://@hostname@@abs_srcdir@/data/no/such/place/badt2.tbl' )
format 'text' (delimiter '|');
--
-- ALTER (partial support)
--
create external table ext (a int, x text)
location ('file://@hostname@@abs_srcdir@/data/no/such/place/badt1.tbl' )
format 'text';
alter table ext drop column a; -- should pass
alter external table ext add column a int; -- pass
alter external table ext drop column a; -- pass
alter external table ext add column extnewcol int not null; -- pass
alter external table ext alter column extnewcol set default 1; -- pass
alter external table ext alter column x type integer using 123; -- should fail (USING doesn't make sense on external table)
alter external table ext alter column x type integer; -- pass
--
-- TRUNCATE/UPDATE/DELETE/INSERT (INTO RET)
--
truncate ext;
delete from ext;
update ext set x='1' where x='2';
insert into ext(x) values(123);
create index ext_index on ext(x); -- should fail
drop table ext; -- should fail (wrong object)
drop external table ext;
----------------------------------------------------------------------
-- CUSTOM PROTOCOLS
----------------------------------------------------------------------
DROP EXTERNAL TABLE IF EXISTS ext_w;
DROP EXTERNAL TABLE IF EXISTS ext_r;
DROP ROLE IF EXISTS extprotu;
CREATE OR REPLACE FUNCTION write_to_file() RETURNS integer as '$libdir/gpextprotocol.so', 'demoprot_export' LANGUAGE C STABLE NO SQL;
CREATE OR REPLACE FUNCTION read_from_file() RETURNS integer as '$libdir/gpextprotocol.so', 'demoprot_import' LANGUAGE C STABLE NO SQL;
DROP PROTOCOL IF EXISTS demoprot;
CREATE TRUSTED PROTOCOL demoprot (readfunc = 'nosuchfunc'); -- should fail
CREATE TRUSTED PROTOCOL demoprot (readfunc = 'boolin'); -- should fail
CREATE TRUSTED PROTOCOL demoprot (readfunc = 'read_from_file', writefunc = 'write_to_file'); -- should succeed
CREATE PROTOCOL demoprot_untrusted (readfunc = 'read_from_file', writefunc = 'write_to_file'); -- should succeed
ALTER PROTOCOL demoprot_untrusted RENAME TO demoprot_untrusted2;
ALTER PROTOCOL demoprot_untrusted2 RENAME TO demoprot_untrusted;
CREATE PROTOCOL demoprot_untrusted2 (readfunc = 'read_from_file', writefunc = 'write_to_file'); -- should succeed
ALTER PROTOCOL demoprot_untrusted RENAME TO demoprot_untrusted2; -- should failed
ALTER PROTOCOL demoprot_untrustedx RENAME TO demoprot_untrusted2; --should failed
CREATE ROLE extprotu NOSUPERUSER;
SET SESSION AUTHORIZATION extprotu;
CREATE WRITABLE EXTERNAL TABLE ext_w(a int) location('demoprot://demoprotfile.txt') format 'text'; -- should fail
CREATE READABLE EXTERNAL TABLE ext_r(a int) location('demoprot://demoprotfile.txt') format 'text'; -- should fail
RESET SESSION AUTHORIZATION;
ALTER PROTOCOL demoprot_untrusted OWNER TO extprotu; -- should fail. protocol is not trusted
GRANT SELECT ON PROTOCOL demoprot_untrusted TO extprotu; -- should fail. protocol is not trusted
GRANT SELECT ON PROTOCOL demoprot TO extprotu;
GRANT INSERT ON PROTOCOL demoprot TO extprotu;
\t on
-- print with tuples-only mode : suppress diff related to user string length.
SELECT ptcname, ptcacl FROM PG_EXTPROTOCOL WHERE ptcname = 'demoprot';
\t off
SET SESSION AUTHORIZATION extprotu;
CREATE WRITABLE EXTERNAL TABLE ext_w(a int) location('demoprot://demoprotfile.txt') format 'text'; -- should succeed
-- For tables using custom protocol should have dependency
SELECT count(*) FROM pg_depend WHERE refclassid = 'pg_extprotocol'::regclass and objid = 'ext_w'::regclass;
CREATE READABLE EXTERNAL TABLE ext_r(a int) location('demoprot://demoprotfile.txt') format 'text'; -- should succeed
-- For tables using custom protocol should have dependency
SELECT count(*) FROM pg_depend WHERE refclassid = 'pg_extprotocol'::regclass and objid = 'ext_r'::regclass;
DROP EXTERNAL TABLE IF EXISTS ext_w;
DROP EXTERNAL TABLE IF EXISTS ext_r;
RESET SESSION AUTHORIZATION;
REVOKE INSERT ON PROTOCOL demoprot FROM extprotu;
SET SESSION AUTHORIZATION extprotu;
CREATE WRITABLE EXTERNAL TABLE ext_w(a int) location('demoprot://demoprotfile.txt') format 'text'; -- should fail
CREATE READABLE EXTERNAL TABLE ext_r(a int) location('demoprot://demoprotfile.txt') format 'text'; -- should succeed
DROP EXTERNAL TABLE ext_r;
RESET SESSION AUTHORIZATION;
REVOKE ALL PRIVILEGES ON PROTOCOL demoprot FROM extprotu;
DROP ROLE IF EXISTS extprotu;
-- Test multi-object DROP
CREATE PROTOCOL demoprot_droptest1 (readfunc = 'read_from_file', writefunc = 'write_to_file');
CREATE PROTOCOL demoprot_droptest2 (readfunc = 'read_from_file', writefunc = 'write_to_file');
DROP PROTOCOL demoprot_droptest1, demoprot_droptest2;
-- Test non-superuser CREATE PROTOCOL, should fail
DROP ROLE IF EXISTS extprot_non_superuser;
CREATE ROLE extprot_non_superuser WITH NOSUPERUSER LOGIN CREATEDB;
SET ROLE extprot_non_superuser;
CREATE PROTOCOL demoprot_non_superuser (readfunc = 'read_from_file', writefunc = 'write_to_file');
CREATE TRUSTED PROTOCOL demoprot_non_superuser (readfunc = 'read_from_file', writefunc = 'write_to_file');
RESET ROLE;
-- Test "DROP OWNED BY" when everything of the protocol is granted to some user.
-- GitHub Issue #12748: https://github.com/greenplum-db/gpdb/issues/12748
CREATE TRUSTED PROTOCOL dummy_protocol_issue_12748 (readfunc = 'read_from_file', writefunc = 'write_to_file');
CREATE ROLE test_role_issue_12748;
GRANT ALL ON PROTOCOL dummy_protocol_issue_12748 TO test_role_issue_12748;
DROP OWNED BY test_role_issue_12748;
-- Clean up.
DROP ROLE test_role_issue_12748;
DROP PROTOCOL dummy_protocol_issue_12748;
-- Test pg_exttable's encoding: QE's encoding should be consistent with QD
-- GitHub Issue #9727: https://github.com/greenplum-db/gpdb/issues/9727
SET client_encoding = 'ISO-8859-1';
CREATE EXTERNAL TABLE issue_9727 (d varchar(20)) location ('gpfdist://9727/d.dat') format 'csv' (DELIMITER '|');
SELECT encoding from pg_exttable where urilocation='{gpfdist://9727:8080/d.dat}';
SELECT encoding from gp_dist_random('pg_exttable') where urilocation='{gpfdist://9727:8080/d.dat}';
DROP FOREIGN TABLE issue_9727;
RESET client_encoding;
-- Test external table location escape
-- GitHub Issue #17179: https://github.com/greenplum-db/gpdb/issues/17179
CREATE READABLE EXTERNAL TABLE public.test_ext
(
id integer
)
LOCATION(
'file://gpdev/tmp/test1|.|tx||t|||',
'file://gpdev/tmp/test2|.|tx||t||||'
)
FORMAT 'TEXT' (
delimiter 'off' null E'\\N' escape E'\\'
)
ENCODING 'UTF8'
LOG ERRORS PERSISTENTLY SEGMENT REJECT LIMIT 10 PERCENT;
SELECT urilocation FROM pg_exttable WHERE reloid = 'public.test_ext'::regclass;
DROP EXTERNAL TABLE public.test_ext;
--
-- WET tests
--
--
-- CREATE (including LIKE, DISTRIBUTED BY)
--
-- positive
create writable external web table wet_pos4(a text, b text) execute 'some command' format 'text';
-- negative
create writable external table wet_neg1(a text, b text) location('file://@hostname@@abs_srcdir@/badt1.tbl') format 'text';
create writable external table wet_neg1(a text, b text) location('gpfdist://foo:7070/wet.out', 'gpfdist://foo:7070/wet.out') format 'text';
create writable external web table wet_pos5(a text, b text) execute 'some command' on segment 0 format 'text';
-- cannot read from a WRITABLE external table.
select * from wet_pos4;
-- Test selecting the CTID system column on an external table. In the past,
-- it was necessary that we generated artificial CTIDs for external table
-- scans, because the planner generated plans that used the CTID attribute
-- to implement certain semi-joins. Nowadays, we use generated row IDs in
-- such plans, and don't need CTID for that purpose anymore.
CREATE EXTERNAL TABLE ext_mpp17980 ( id int , id1 int , id2 int)
LOCATION ('file://@hostname@@abs_srcdir@/data/mpp17980.data')
FORMAT 'CSV' ( DELIMITER ',' NULL ' ');
CREATE TABLE mpp17980 (id int, date date, amt decimal(10,2))
DISTRIBUTED randomly PARTITION BY RANGE (date)
( START (date '2008-01-01') INCLUSIVE END (date '2009-01-01') EXCLUSIVE
EVERY (INTERVAL '1 month') );
INSERT INTO mpp17980 VALUES ( 1,'2008-02-20',122.11);
SELECT COUNT(*) FROM ext_mpp17980 WHERE id IN ( 1 ) ; -- This returns 18 tuples
SELECT COUNT(*) FROM ext_mpp17980 WHERE id IN ( SELECT id FROM mpp17980 ) ; -- This should return 18 tuples but returns only 1
SELECT ctid, * FROM ext_mpp17980;
DROP EXTERNAL TABLE ext_mpp17980;
DROP TABLE mpp17980;
COPY (VALUES('1,2'),('1,2,3'),('1,'),('1')) TO '@abs_srcdir@/data/tableless.csv';
CREATE TABLE tableless_heap(a int, b int);
COPY tableless_heap FROM '@abs_srcdir@/data/tableless.csv' CSV LOG ERRORS SEGMENT REJECT LIMIT 10;
SELECT relname, linenum, errmsg FROM gp_read_error_log('tableless_heap');
create table errlog_save as select * from gp_read_error_log('tableless_heap');
select count(*) from errlog_save;
SELECT gp_truncate_error_log('tableless_heap');
SELECT relname, linenum, errmsg FROM gp_read_error_log('tableless_heap');
create external table tableless_ext(a int, b int)
location ('file://@hostname@@abs_srcdir@/data/tableless.csv')
format 'csv'
log errors segment reject limit 10;
select * from tableless_ext;
SELECT relname, linenum, errmsg FROM gp_read_error_log('tableless_ext');
SELECT (gp_read_error_log('tableless_ext')).errmsg;
SELECT gp_truncate_error_log('tableless_ext');
SELECT relname, linenum, errmsg FROM gp_read_error_log('tableless_ext');
select * from tableless_ext;
SELECT gp_truncate_error_log('*');
select * from tableless_ext;
SELECT gp_truncate_error_log('*.*');
SELECT relname, linenum, errmsg FROM gp_read_error_log('tableless_ext');
--
-- These fail because there are more locations than there are segments.
--
-- As written, if you have a large enough cluster, with more than 20
-- segments, this will fail to test what's intended. But we don't currently
-- run automated tests like that, and you'll get a different error message,
-- so it won't fail silently.
--
create external table ret_too_many_uris(a text, b text) location(
'gpfdist://foo.invalid:7070/ret.tbl1', 'gpfdist://foo.invalid:7070/ret.tbl2',
'gpfdist://foo.invalid:7070/ret.tbl3', 'gpfdist://foo.invalid:7070/ret.tbl4',
'gpfdist://foo.invalid:7070/ret.tbl5', 'gpfdist://foo.invalid:7070/ret.tbl6',
'gpfdist://foo.invalid:7070/ret.tbl7', 'gpfdist://foo.invalid:7070/ret.tbl8',
'gpfdist://foo.invalid:7070/ret.tbl9', 'gpfdist://foo.invalid:7070/ret.tbl10',
'gpfdist://foo.invalid:7070/ret.tbl11', 'gpfdist://foo.invalid:7070/ret.tbl12',
'gpfdist://foo.invalid:7070/ret.tbl13', 'gpfdist://foo.invalid:7070/ret.tbl14',
'gpfdist://foo.invalid:7070/ret.tbl15', 'gpfdist://foo.invalid:7070/ret.tbl16',
'gpfdist://foo.invalid:7070/ret.tbl17', 'gpfdist://foo.invalid:7070/ret.tbl18',
'gpfdist://foo.invalid:7070/ret.tbl19', 'gpfdist://foo.invalid:7070/ret.tbl20'
) format 'text';
\d ret_too_many_uris
select * from ret_too_many_uris;
create writable external table wet_too_many_uris(a text, b text) location(
'gpfdist://foo.invalid:7070/wet.out1', 'gpfdist://foo.invalid:7070/wet.out2',
'gpfdist://foo.invalid:7070/wet.out3', 'gpfdist://foo.invalid:7070/wet.out4',
'gpfdist://foo.invalid:7070/wet.out5', 'gpfdist://foo.invalid:7070/wet.out6',
'gpfdist://foo.invalid:7070/wet.out7', 'gpfdist://foo.invalid:7070/wet.out8',
'gpfdist://foo.invalid:7070/wet.out9', 'gpfdist://foo.invalid:7070/wet.out10',
'gpfdist://foo.invalid:7070/wet.out11', 'gpfdist://foo.invalid:7070/wet.out12',
'gpfdist://foo.invalid:7070/wet.out13', 'gpfdist://foo.invalid:7070/wet.out14',
'gpfdist://foo.invalid:7070/wet.out15', 'gpfdist://foo.invalid:7070/wet.out16',
'gpfdist://foo.invalid:7070/wet.out17', 'gpfdist://foo.invalid:7070/wet.out18',
'gpfdist://foo.invalid:7070/wet.out19', 'gpfdist://foo.invalid:7070/wet.out20'
) format 'text';
insert into wet_too_many_uris values ('foo', 'bar');
-- Test for error log functionality
-- Scan with no errors
CREATE EXTERNAL TABLE exttab_basic_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
-- Empty error log
SELECT * FROM gp_read_error_log('exttab_basic_1');
SELECT COUNT(*) FROM exttab_basic_1;
-- Error log should still be empty
SELECT * FROM gp_read_error_log('exttab_basic_1');
-- test ON COORDINATOR without LOG ERRORS, return empty results for all rows error out
CREATE EXTERNAL WEB TABLE exttab_basic_error_1( i int )
EXECUTE E'cat @abs_srcdir@/data/exttab.data' ON COORDINATOR
FORMAT 'TEXT' (DELIMITER '|')
SEGMENT REJECT LIMIT 20;
SELECT * FROM exttab_basic_error_1;
DROP EXTERNAL TABLE IF EXISTS exttab_basic_error_1;
-- test ON MASTER still works (this syntax will be removed in GPDB8 and forward)
CREATE EXTERNAL WEB TABLE exttab_basic_error_1( i int )
EXECUTE E'cat @abs_srcdir@/data/exttab.data' ON MASTER
FORMAT 'TEXT' (DELIMITER '|')
SEGMENT REJECT LIMIT 20;
SELECT * FROM exttab_basic_error_1;
-- Some errors without exceeding reject limit
CREATE EXTERNAL TABLE exttab_basic_2( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- should not error out as segment reject limit will not be reached
SELECT * FROM exttab_basic_2 order by i;
-- Error rows logged
select count(*) from gp_read_error_log('exttab_basic_2');
-- Errors with exceeding reject limit
CREATE EXTERNAL TABLE exttab_basic_3( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
-- should error out as segment reject limit will be reached
SELECT * FROM exttab_basic_3;
-- Error log should be populated
select count(*) > 0 from gp_read_error_log('exttab_basic_3');
-- Insert into another table
CREATE EXTERNAL TABLE exttab_basic_4( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 100;
CREATE TABLE exttab_insert_1 (LIKE exttab_basic_4);
-- Insert should go through fine
INSERT INTO exttab_insert_1 SELECT * FROM exttab_basic_4;
-- Error log should be populated
select count(*) > 0 from gp_read_error_log('exttab_basic_4');
-- Use the same error log above
CREATE EXTERNAL TABLE exttab_basic_5( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 5;
-- Insert should fail
INSERT INTO exttab_insert_1 select * from exttab_basic_5;
SELECT * from exttab_insert_1 order by i;
-- Error log should have additional rows that were rejected by the above query
SELECT count(*) from gp_read_error_log('exttab_basic_5');
-- CTAS
CREATE EXTERNAL TABLE exttab_basic_6( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 100;
CREATE TABLE exttab_ctas_1 as SELECT * FROM exttab_basic_6;
-- CTAS should go through fine
SELECT * FROM exttab_ctas_1 order by i;
-- Error log should have six rows that were rejected
select count(*) from gp_read_error_log('exttab_basic_6');
CREATE EXTERNAL TABLE exttab_basic_7( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 5;
-- CTAS should fail
CREATE TABLE exttab_ctas_2 AS select * from exttab_basic_7;
-- Table should not exist
SELECT * from exttab_ctas_2 order by i;
-- Error table should have additional rows that were rejected by the above query
SELECT count(*) from gp_read_error_log('exttab_basic_7');
-- Drop external table gets rid off error logs
DROP EXTERNAL TABLE IF EXISTS exttab_error_log;
CREATE EXTERNAL TABLE exttab_error_log( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
SELECT COUNT(*) FROM exttab_error_log;
SELECT COUNT(*) FROM gp_read_error_log('exttab_error_log');
DROP EXTERNAL TABLE exttab_error_log;
SELECT COUNT(*) FROM gp_read_error_log('exttab_error_log');
-- Insert into another table with unique constraints
CREATE EXTERNAL TABLE exttab_constraints_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- Should not error out
SELECT COUNT(*) FROM exttab_constraints_1;
-- Error log should have a couple of rows
SELECT COUNT(*) from gp_read_error_log('exttab_constraints_1');
CREATE TABLE exttab_constraints_insert_1 (LIKE exttab_constraints_1) distributed by (i);
ALTER TABLE exttab_constraints_insert_1 SET DISTRIBUTED BY(j);
ALTER TABLE exttab_constraints_insert_1 ADD CONSTRAINT exttab_uniq_constraint_1 UNIQUE (j);
-- This should fail
select gp_truncate_error_log('exttab_constraints_1');
INSERT INTO exttab_constraints_insert_1 SELECT * FROM exttab_constraints_1;
SELECT COUNT(*) FROM gp_read_error_log('exttab_constraints_1');
-- CTE with segment reject limit reached
-- does not reach reject limit
CREATE EXTERNAL TABLE exttab_cte_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- reaches reject limit, use the same err table
CREATE EXTERNAL TABLE exttab_cte_2( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
with cte1 as
(
SELECT e1.i, e2.j FROM exttab_cte_2 e1, exttab_cte_1 e2
WHERE e1.i = e2.i ORDER BY e1.i
)
SELECT * FROM cte1 ORDER BY cte1.i;
select count(*) from gp_read_error_log('exttab_cte_2');
-- start_ignore
select gp_read_error_log('exttab_cte_2');
-- end_ignore
-- CTE without segment reject limit exceeded
select gp_truncate_error_log('exttab_cte_1');
select gp_truncate_error_log('exttab_cte_2');
with cte1 as
(
SELECT e1.i, e2.j FROM exttab_cte_1 e1, exttab_cte_1 e2 WHERE e1.i = e2.i AND e1.i > 5 ORDER BY e1.i
)
SELECT cte1.i , cte1.j FROM cte1 ORDER BY cte1.i;
-- Check permissions with gp_truncate_error_log and gp_read_error_log
-- does not reach reject limit
CREATE EXTERNAL TABLE exttab_permissions_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- reaches reject limit
CREATE EXTERNAL TABLE exttab_permissions_2( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
-- generate some error logs
SELECT COUNT(*) FROM exttab_permissions_1;
SELECT COUNT(*) FROM exttab_permissions_2;
-- Only superuser can do gp_truncate_error_log('*.*')
DROP ROLE IF EXISTS exttab_non_superuser;
CREATE ROLE exttab_non_superuser WITH NOSUPERUSER LOGIN CREATEDB;
SET ROLE exttab_non_superuser;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_1');
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_2');
SELECT gp_truncate_error_log('exttab_permissions_1');
SELECT gp_truncate_error_log('exttab_permissions_2');
SELECT gp_truncate_error_log('*');
SELECT gp_truncate_error_log('*.*');
RESET ROLE;
DROP ROLE IF EXISTS exttab_superuser;
CREATE ROLE exttab_superuser WITH SUPERUSER LOGIN;
SET ROLE exttab_superuser;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_2');
SELECT gp_truncate_error_log('*');
SELECT gp_truncate_error_log('*.*');
SELECT gp_truncate_error_log('exttab_permissions_1');
SELECT gp_truncate_error_log('exttab_permissions_2');
RESET ROLE;
SELECT * FROM gp_read_error_log('exttab_permissions_1');
SELECT * FROM gp_read_error_log('exttab_permissions_2');
-- Only database owner can do gp_truncate_error_log('*')
DROP DATABASE IF EXISTS exttab_db;
DROP ROLE IF EXISTS exttab_user1;
DROP ROLE IF EXISTS exttab_user2;
CREATE ROLE exttab_user1 WITH NOSUPERUSER LOGIN;
CREATE ROLE exttab_user2 WITH NOSUPERUSER LOGIN;
CREATE DATABASE exttab_db WITH OWNER=exttab_user1;
\c exttab_db
-- generate some error logs in this db
CREATE EXTERNAL TABLE exttab_permissions_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
SELECT COUNT(*) FROM exttab_permissions_1 e1, exttab_permissions_1 e2;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_1');
SET ROLE exttab_user2;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_1');
SELECT gp_truncate_error_log('*');
SELECT gp_truncate_error_log('*.*');
SELECT gp_truncate_error_log('exttab_permissions_1');
SET ROLE exttab_user1;
-- Database owner can still not perform read / truncate on specific tables. This follows the same mechanism as TRUNCATE table.
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_1');
SELECT gp_truncate_error_log('exttab_permissions_1');
SELECT gp_truncate_error_log('*');
-- should fail
SELECT gp_truncate_error_log('*.*');
RESET ROLE;
SELECT * FROM gp_read_error_log('exttab_permissions_1');
\c regression
DROP ROLE IF EXISTS errlog_exttab_user3;
DROP ROLE IF EXISTS errlog_exttab_user4;
CREATE ROLE errlog_exttab_user3 WITH NOSUPERUSER LOGIN;
CREATE ROLE errlog_exttab_user4 WITH NOSUPERUSER LOGIN;
-- generate some error logs in this db
CREATE EXTERNAL TABLE exttab_permissions_3( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
SELECT COUNT(*) FROM exttab_permissions_3 e1, exttab_permissions_3 e2;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_3');
ALTER EXTERNAL TABLE exttab_permissions_3 OWNER TO errlog_exttab_user3;
-- This should fail with non table owner
SET ROLE errlog_exttab_user4;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_3');
SELECT gp_truncate_error_log('exttab_permissions_3');
-- should go through fine with table owner
SET ROLE errlog_exttab_user3;
SELECT gp_truncate_error_log('exttab_permissions_3');
RESET ROLE;
SELECT * FROM gp_read_error_log('exttab_permissions_3');
-- Grant TRUNCATE permission on table to a non table owner and make sure he is able to do gp_truncate_error_log
GRANT TRUNCATE on exttab_permissions_3 to errlog_exttab_user4;
SELECT COUNT(*) FROM exttab_permissions_3 e1, exttab_permissions_3 e2;
SELECT COUNT(*) FROM gp_read_error_log('exttab_permissions_3');
SET ROLE errlog_exttab_user4;
SELECT gp_truncate_error_log('exttab_permissions_3');
RESET ROLE;
SELECT * FROM gp_read_error_log('exttab_permissions_3');
-- Subqueries reaching segment reject limit
-- does not reach reject limit
CREATE EXTERNAL TABLE exttab_subq_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- reaches reject limit, use the same err table
CREATE EXTERNAL TABLE exttab_subq_2( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
SELECT sum(distinct e1.i), sum(distinct e2.i), e1.j FROM
(SELECT i, j FROM exttab_subq_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subq_2 WHERE i < 10) e2
group by e1.j;
SELECT COUNT(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_subq_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subq_2')
) FOO;
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT sum(distinct e1.i), sum(distinct e2.i), e1.j FROM
(SELECT i, j FROM exttab_subq_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subq_1 WHERE i < 10) e2
group by e1.j
HAVING sum(distinct e1.i) > (SELECT max(i) FROM exttab_subq_2);
SELECT COUNT(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_subq_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subq_2')
) FOO;
-- Subqueries without reaching segment reject limit
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT sum(distinct e1.i), sum(distinct e2.i), e1.j FROM
(SELECT i, j FROM exttab_subq_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subq_1 WHERE i < 10) e2
group by e1.j order by 3,2,1;
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT sum(distinct e1.i), sum(distinct e2.i), e1.j FROM
(SELECT i, j FROM exttab_subq_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subq_1 WHERE i < 10) e2
group by e1.j
HAVING sum(distinct e1.i) > (SELECT max(i) FROM exttab_subq_1);
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT e1.i , e1.j FROM
exttab_subq_1 e1, exttab_subq_1 e2
WHERE e1.j = e2.j and
e1.i + 1 IN ( SELECT i from exttab_subq_1 WHERE i <= e1.i);
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT ( SELECT i FROM exttab_subq_2 WHERE i <= e1.i) as i, e1.j
FROM exttab_subq_2 e1, exttab_subq_1 e2
WHERE e1.i = e2.i;
-- CSQ
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT e1.i , e1.j FROM
exttab_subq_1 e1, exttab_subq_1 e2
WHERE e1.j = e2.j and
e1.i + 1 IN ( SELECT i from exttab_subq_2 WHERE i <= e1.i);
SELECT COUNT(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_subq_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subq_2')
) FOO;
SELECT gp_truncate_error_log('exttab_subq_1');
SELECT gp_truncate_error_log('exttab_subq_2');
SELECT ( SELECT i FROM exttab_subq_2 WHERE i <= e1.i) as i, e1.j
FROM exttab_subq_2 e1, exttab_subq_1 e2
WHERE e1.i = e2.i;
SELECT COUNT(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_subq_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subq_2')
) FOO;
-- TRUNCATE / delete / write to error logs within subtransactions
-- does not reach reject limit
CREATE EXTERNAL TABLE exttab_subtxs_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- reaches reject limit, use the same err table
CREATE EXTERNAL TABLE exttab_subtxs_2( i int, j text )
LOCATION ('file://@hostname@:@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
-- Populate error logs before transaction
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
SELECT COUNT(*)
FROM (
SELECT * FROM gp_read_error_log('exttab_subtxs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subtxs_2')
) FOO;
BEGIN;
savepoint s1;
SELECT gp_truncate_error_log('exttab_subtxs_1');
SELECT gp_truncate_error_log('exttab_subtxs_2');
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
-- should have written rows into error log
SELECT count(*) FROM
(
SELECT * FROM gp_read_error_log('exttab_subtxs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subtxs_2')
) FOO;
savepoint s2;
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
savepoint s3;
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subtxs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
ROLLBACK TO s2;
-- rollback should not rollback the error rows written from within the transaction
SELECT count(*) FROM
(
SELECT * FROM gp_read_error_log('exttab_subtxs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subtxs_2')
) FOO;
-- Make the tx fail, segment reject limit reaches here
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_subtxs_2 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_subtxs_2 WHERE i < 10) e2
WHERE e1.i = e2.i;
COMMIT;
-- Error logs should not have been rolled back.
-- Check that number of errors is greater than 12 instead of checking for
-- actual number of errors, since the transaction might get aborted even before
-- rows are scanned on other segments if one of the segments hits the segment
-- reject limit. The 12 errors are from previous scans of the external table.
SELECT count(*) > 12 FROM
(
SELECT * FROM gp_read_error_log('exttab_subtxs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_subtxs_2')
) FOO;
-- TRUNCATE error logs within tx , abort transaction
-- does not reach reject limit
CREATE EXTERNAL TABLE exttab_txs_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- reaches reject limit, use the same err table
CREATE EXTERNAL TABLE exttab_txs_2( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
-- Populate error log before transaction
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_txs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_txs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
SELECT count(*) FROM
(
SELECT * FROM gp_read_error_log('exttab_txs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_txs_2')
) FOO;
BEGIN;
SELECT gp_truncate_error_log('exttab_txs_1');
SELECT gp_truncate_error_log('exttab_txs_2');
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_txs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_txs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
ABORT;
-- Check that number of errors is greater than zero instead of checking the
-- actual number of errors since the transaction might get aborted even before
-- rows are scanned on other segments if one of the segments hits the segment
-- reject limit.
SELECT count(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_txs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_txs_2')
) FOO;
-- TRUNCATE error logs within txs , with segment reject limit reached
-- Populate error log before transaction
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_txs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_txs_1 WHERE i < 10) e2
WHERE e1.i = e2.i;
SELECT count(*) FROM
(
SELECT * FROM gp_read_error_log('exttab_txs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_txs_2')
) FOO;
BEGIN;
SELECT gp_truncate_error_log('exttab_txs_1');
SELECT gp_truncate_error_log('exttab_txs_2');
-- This should abort the transaction
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_txs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_txs_2 WHERE i < 10) e2
WHERE e1.i = e2.i;
COMMIT;
-- Additional error rows should have been inserted into the error logs even if the tx is aborted.
-- Truncate of error logs should not be rolled back even if the transaction is aborted. All operation on error logs are persisted.
-- Check that number of errors is greater than zero instead of checking for
-- actual number of errors, since the transaction might get aborted even before
-- rows are scanned on other segments if one of the segments hits the segment
-- reject limit.
SELECT count(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_txs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_txs_2')
) FOO;
-- Creating external table with error log within txs with segment reject limits reached
SELECT gp_truncate_error_log('exttab_txs_1');
SELECT gp_truncate_error_log('exttab_txs_2');
DROP EXTERNAL TABLE IF EXISTS exttab_txs_3;
DROP EXTERNAL TABLE IF EXISTS exttab_txs_4;
BEGIN;
-- create an external table that will reach segment reject limit
-- reaches reject limit
CREATE EXTERNAL TABLE exttab_txs_3( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
-- new error log, within segment reject limit
CREATE EXTERNAL TABLE exttab_txs_4( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_txs_4 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_txs_4 WHERE i < 10) e2
WHERE e1.i = e2.i order by e1.i;
-- should be populated correctly
SELECT count(*) FROM gp_read_error_log('exttab_txs_4');
-- should error out and abort the transaction
SELECT e1.i, e2.j FROM
(SELECT i, j FROM exttab_txs_3 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_txs_4 WHERE i < 10) e2
WHERE e1.i = e2.i order by e1.i;
COMMIT;
-- Error logs should not exist for these tables that would have been rolled back
SELECT count(*) FROM gp_read_error_log('exttab_txs_3');
SELECT count(*) FROM gp_read_error_log('exttab_txs_4');
-- external tables created within aborted transactions should not exist
SELECT count(*) FROM exttab_txs_3;
SELECT count(*) FROM exttab_txs_4;
-- UDFS with segment reject limit reached
-- does not reach reject limit
CREATE EXTERNAL TABLE exttab_udfs_1( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 10;
-- reaches reject limit, use the same err table
CREATE EXTERNAL TABLE exttab_udfs_2( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_more_errors.data') FORMAT 'TEXT' (DELIMITER '|')
LOG ERRORS SEGMENT REJECT LIMIT 2;
CREATE OR REPLACE FUNCTION exttab_udfs_func1 ()
RETURNS boolean
AS $$
BEGIN
EXECUTE 'SELECT sum(distinct e1.i) as sum_i, sum(distinct e2.i) as sum_j, e1.j as j FROM
(SELECT i, j FROM exttab_udfs_1 WHERE i < 5 ) e1,
(SELECT i, j FROM exttab_udfs_2 WHERE i < 10) e2
group by e1.j';
RETURN 1;
END;
$$
LANGUAGE plpgsql volatile;
-- Should fail
SELECT * FROM exttab_udfs_func1();
-- Should be populated
SELECT COUNT(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_udfs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_udfs_2')
) FOO;
-- INSERT INTO from a udf
DROP TABLE IF EXISTS exttab_udfs_insert_1;
CREATE TABLE exttab_udfs_insert_1(a boolean);
SELECT gp_truncate_error_log('exttab_udfs_1');
SELECT gp_truncate_error_log('exttab_udfs_2');
-- Should fail
INSERT INTO exttab_udfs_insert_1 SELECT * FROM exttab_udfs_func1();
SELECT * FROM exttab_udfs_insert_1;
-- Error table should be populated correctly
SELECT COUNT(*) > 0 FROM
(
SELECT * FROM gp_read_error_log('exttab_udfs_1')
UNION ALL
SELECT * FROM gp_read_error_log('exttab_udfs_2')
) FOO;
-- UDFs with INSERT INTO with segment reject limit reached
DROP TABLE IF EXISTS exttab_udfs_insert_2;
CREATE TABLE exttab_udfs_insert_2 (LIKE exttab_udfs_1);
CREATE OR REPLACE FUNCTION exttab_udfs_func2 ()
RETURNS boolean
AS $$
DECLARE
r RECORD;
cnt integer;
result boolean;
BEGIN
SELECT INTO result gp_truncate_error_log('exttab_udfs_1');
SELECT INTO result gp_truncate_error_log('exttab_udfs_2');
INSERT INTO exttab_udfs_insert_2
SELECT i, j from exttab_udfs_1;
cnt := 0;
FOR r in SELECT * FROM gp_read_error_log('exttab_udfs_1') LOOP
-- just looping through the error log
cnt := cnt + 1;
END LOOP;
IF cnt <= 0 THEN
RAISE EXCEPTION 'Error log should not be empty';
END IF;
SELECT count(*) INTO cnt FROM exttab_udfs_insert_2;
-- should be 8
IF cnt <> 8 THEN
RAISE EXCEPTION 'Unexpected number of rows inserted';
END IF;
-- Now make insert into fail
INSERT INTO exttab_udfs_insert_2
SELECT i, j from exttab_udfs_2;
-- Should not reach here
cnt := 0;
FOR r in SELECT * FROM gp_read_error_log('exttab_udfs_2') LOOP
-- just looping through the error log
cnt := cnt + 1;
END LOOP;
IF cnt <= 0 THEN
RAISE EXCEPTION 'Error table should not be empty';
END IF;
RETURN 1;
END;
$$