@@ -185,12 +185,23 @@ select * from T_pkey2 order by key1 using @<, key2 collate "C";
185
185
186
186
-- show dump of trigger data
187
187
insert into trigger_test values(1,'insert');
188
- NOTICE: NEW: {i: 1, v: insert}
188
+ NOTICE: NEW: {}
189
+ NOTICE: OLD: {}
190
+ NOTICE: TG_level: STATEMENT
191
+ NOTICE: TG_name: statement_trigger
192
+ NOTICE: TG_op: INSERT
193
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
194
+ NOTICE: TG_relid: bogus:12345
195
+ NOTICE: TG_table_name: trigger_test
196
+ NOTICE: TG_table_schema: public
197
+ NOTICE: TG_when: BEFORE
198
+ NOTICE: args: {42 {statement trigger}}
199
+ NOTICE: NEW: {i: 1, test_argisnull: f, test_return_null: f, test_skip: f, v: insert}
189
200
NOTICE: OLD: {}
190
201
NOTICE: TG_level: ROW
191
202
NOTICE: TG_name: show_trigger_data_trig
192
203
NOTICE: TG_op: INSERT
193
- NOTICE: TG_relatts: {{} i v}
204
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull }
194
205
NOTICE: TG_relid: bogus:12345
195
206
NOTICE: TG_table_name: trigger_test
196
207
NOTICE: TG_table_schema: public
@@ -232,30 +243,77 @@ NOTICE: TG_table_name: trigger_test_view
232
243
NOTICE: TG_table_schema: public
233
244
NOTICE: TG_when: {INSTEAD OF}
234
245
NOTICE: args: {24 {skidoo view}}
246
+ update trigger_test set v = 'update', test_skip=true where i = 1;
247
+ NOTICE: NEW: {}
248
+ NOTICE: OLD: {}
249
+ NOTICE: TG_level: STATEMENT
250
+ NOTICE: TG_name: statement_trigger
251
+ NOTICE: TG_op: UPDATE
252
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
253
+ NOTICE: TG_relid: bogus:12345
254
+ NOTICE: TG_table_name: trigger_test
255
+ NOTICE: TG_table_schema: public
256
+ NOTICE: TG_when: BEFORE
257
+ NOTICE: args: {42 {statement trigger}}
258
+ NOTICE: SKIPPING OPERATION UPDATE
235
259
update trigger_test set v = 'update' where i = 1;
236
- NOTICE: NEW: {i: 1, v: update}
237
- NOTICE: OLD: {i: 1, v: insert}
260
+ NOTICE: NEW: {}
261
+ NOTICE: OLD: {}
262
+ NOTICE: TG_level: STATEMENT
263
+ NOTICE: TG_name: statement_trigger
264
+ NOTICE: TG_op: UPDATE
265
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
266
+ NOTICE: TG_relid: bogus:12345
267
+ NOTICE: TG_table_name: trigger_test
268
+ NOTICE: TG_table_schema: public
269
+ NOTICE: TG_when: BEFORE
270
+ NOTICE: args: {42 {statement trigger}}
271
+ NOTICE: NEW: {i: 1, test_argisnull: f, test_return_null: f, test_skip: f, v: update}
272
+ NOTICE: OLD: {i: 1, test_argisnull: f, test_return_null: f, test_skip: f, v: insert}
238
273
NOTICE: TG_level: ROW
239
274
NOTICE: TG_name: show_trigger_data_trig
240
275
NOTICE: TG_op: UPDATE
241
- NOTICE: TG_relatts: {{} i v}
276
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull }
242
277
NOTICE: TG_relid: bogus:12345
243
278
NOTICE: TG_table_name: trigger_test
244
279
NOTICE: TG_table_schema: public
245
280
NOTICE: TG_when: BEFORE
246
281
NOTICE: args: {23 skidoo}
247
282
delete from trigger_test;
248
283
NOTICE: NEW: {}
249
- NOTICE: OLD: {i: 1, v: update}
284
+ NOTICE: OLD: {}
285
+ NOTICE: TG_level: STATEMENT
286
+ NOTICE: TG_name: statement_trigger
287
+ NOTICE: TG_op: DELETE
288
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
289
+ NOTICE: TG_relid: bogus:12345
290
+ NOTICE: TG_table_name: trigger_test
291
+ NOTICE: TG_table_schema: public
292
+ NOTICE: TG_when: BEFORE
293
+ NOTICE: args: {42 {statement trigger}}
294
+ NOTICE: NEW: {}
295
+ NOTICE: OLD: {i: 1, test_argisnull: f, test_return_null: f, test_skip: f, v: update}
250
296
NOTICE: TG_level: ROW
251
297
NOTICE: TG_name: show_trigger_data_trig
252
298
NOTICE: TG_op: DELETE
253
- NOTICE: TG_relatts: {{} i v}
299
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull }
254
300
NOTICE: TG_relid: bogus:12345
255
301
NOTICE: TG_table_name: trigger_test
256
302
NOTICE: TG_table_schema: public
257
303
NOTICE: TG_when: BEFORE
258
304
NOTICE: args: {23 skidoo}
305
+ truncate trigger_test;
306
+ NOTICE: NEW: {}
307
+ NOTICE: OLD: {}
308
+ NOTICE: TG_level: STATEMENT
309
+ NOTICE: TG_name: statement_trigger
310
+ NOTICE: TG_op: TRUNCATE
311
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
312
+ NOTICE: TG_relid: bogus:12345
313
+ NOTICE: TG_table_name: trigger_test
314
+ NOTICE: TG_table_schema: public
315
+ NOTICE: TG_when: BEFORE
316
+ NOTICE: args: {42 {statement trigger}}
259
317
-- Test composite-type arguments
260
318
select tcl_composite_arg_ref1(row('tkey', 42, 'ref2'));
261
319
tcl_composite_arg_ref1
@@ -288,6 +346,22 @@ select tcl_argisnull(null);
288
346
t
289
347
(1 row)
290
348
349
+ -- should error
350
+ insert into trigger_test(test_argisnull) values(true);
351
+ NOTICE: NEW: {}
352
+ NOTICE: OLD: {}
353
+ NOTICE: TG_level: STATEMENT
354
+ NOTICE: TG_name: statement_trigger
355
+ NOTICE: TG_op: INSERT
356
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
357
+ NOTICE: TG_relid: bogus:12345
358
+ NOTICE: TG_table_name: trigger_test
359
+ NOTICE: TG_table_schema: public
360
+ NOTICE: TG_when: BEFORE
361
+ NOTICE: args: {42 {statement trigger}}
362
+ ERROR: argisnull cannot be used in triggers
363
+ select trigger_data();
364
+ ERROR: trigger functions can only be called as triggers
291
365
-- Test spi_lastoid primitive
292
366
create temp table t1 (f1 int);
293
367
select tcl_lastoid('t1');
@@ -304,14 +378,14 @@ select tcl_lastoid('t2') > 0;
304
378
(1 row)
305
379
306
380
-- test some error cases
307
- CREATE FUNCTION tcl_error(OUT a int, OUT b int) AS $$return {$$ LANGUAGE pltcl;
308
- SELECT tcl_error();
381
+ create function tcl_error(out a int, out b int) as $$return {$$ language pltcl;
382
+ select tcl_error();
309
383
ERROR: missing close-brace
310
- CREATE FUNCTION bad_record(OUT a text, OUT b text) AS $$return [list a]$$ LANGUAGE pltcl;
311
- SELECT bad_record();
384
+ create function bad_record(out a text, out b text) as $$return [list a]$$ language pltcl;
385
+ select bad_record();
312
386
ERROR: column name/value list must have even number of elements
313
- CREATE FUNCTION bad_field(OUT a text, OUT b text) AS $$return [list a 1 b 2 cow 3]$$ LANGUAGE pltcl;
314
- SELECT bad_field();
387
+ create function bad_field(out a text, out b text) as $$return [list a 1 b 2 cow 3]$$ language pltcl;
388
+ select bad_field();
315
389
ERROR: column name/value list contains nonexistent column name "cow"
316
390
-- test compound return
317
391
select * from tcl_test_cube_squared(5);
@@ -351,16 +425,238 @@ select 1, tcl_test_sequence(0,5);
351
425
1 | 4
352
426
(5 rows)
353
427
354
- CREATE FUNCTION non_srf() RETURNS int AS $$return_next 1$$ LANGUAGE pltcl;
428
+ create function non_srf() returns int as $$return_next 1$$ language pltcl;
355
429
select non_srf();
356
430
ERROR: return_next cannot be used in non-set-returning functions
357
- CREATE FUNCTION bad_record_srf(OUT a text, OUT b text) RETURNS SETOF record AS $$
431
+ create function bad_record_srf(out a text, out b text) returns setof record as $$
358
432
return_next [list a]
359
- $$ LANGUAGE pltcl;
360
- SELECT bad_record_srf();
433
+ $$ language pltcl;
434
+ select bad_record_srf();
361
435
ERROR: column name/value list must have even number of elements
362
- CREATE FUNCTION bad_field_srf(OUT a text, OUT b text) RETURNS SETOF record AS $$
436
+ create function bad_field_srf(out a text, out b text) returns setof record as $$
363
437
return_next [list a 1 b 2 cow 3]
364
- $$ LANGUAGE pltcl;
365
- SELECT bad_field_srf();
438
+ $$ language pltcl;
439
+ select bad_field_srf();
366
440
ERROR: column name/value list contains nonexistent column name "cow"
441
+ -- test quote
442
+ select tcl_eval('quote foo bar');
443
+ ERROR: wrong # args: should be "quote string"
444
+ select tcl_eval('quote [format %c 39]');
445
+ tcl_eval
446
+ ----------
447
+ ''
448
+ (1 row)
449
+
450
+ select tcl_eval('quote [format %c 92]');
451
+ tcl_eval
452
+ ----------
453
+ \\
454
+ (1 row)
455
+
456
+ -- Test argisnull
457
+ select tcl_eval('argisnull');
458
+ ERROR: wrong # args: should be "argisnull argno"
459
+ select tcl_eval('argisnull 14');
460
+ ERROR: argno out of range
461
+ select tcl_eval('argisnull abc');
462
+ ERROR: expected integer but got "abc"
463
+ -- Test return_null
464
+ select tcl_eval('return_null 14');
465
+ ERROR: wrong # args: should be "return_null "
466
+ -- should error
467
+ insert into trigger_test(test_return_null) values(true);
468
+ NOTICE: NEW: {}
469
+ NOTICE: OLD: {}
470
+ NOTICE: TG_level: STATEMENT
471
+ NOTICE: TG_name: statement_trigger
472
+ NOTICE: TG_op: INSERT
473
+ NOTICE: TG_relatts: {{} i v {} test_skip test_return_null test_argisnull}
474
+ NOTICE: TG_relid: bogus:12345
475
+ NOTICE: TG_table_name: trigger_test
476
+ NOTICE: TG_table_schema: public
477
+ NOTICE: TG_when: BEFORE
478
+ NOTICE: args: {42 {statement trigger}}
479
+ ERROR: return_null cannot be used in triggers
480
+ -- Test spi_exec
481
+ select tcl_eval('spi_exec');
482
+ ERROR: wrong # args: should be "spi_exec ?-count n? ?-array name? query ?loop body?"
483
+ select tcl_eval('spi_exec -count');
484
+ ERROR: missing argument to -count or -array
485
+ select tcl_eval('spi_exec -array');
486
+ ERROR: missing argument to -count or -array
487
+ select tcl_eval('spi_exec -count abc');
488
+ ERROR: expected integer but got "abc"
489
+ select tcl_eval('spi_exec query loop body toomuch');
490
+ ERROR: wrong # args: should be "query ?loop body?"
491
+ select tcl_eval('spi_exec "begin; rollback;"');
492
+ ERROR: pltcl: SPI_execute failed: SPI_ERROR_TRANSACTION
493
+ -- Test spi_execp
494
+ select tcl_eval('spi_execp');
495
+ ERROR: missing argument to -count or -array
496
+ select tcl_eval('spi_execp -count');
497
+ ERROR: missing argument to -array, -count or -nulls
498
+ select tcl_eval('spi_execp -array');
499
+ ERROR: missing argument to -array, -count or -nulls
500
+ select tcl_eval('spi_execp -count abc');
501
+ ERROR: expected integer but got "abc"
502
+ select tcl_eval('spi_execp -nulls');
503
+ ERROR: missing argument to -array, -count or -nulls
504
+ select tcl_eval('spi_execp ""');
505
+ ERROR: invalid queryid ''
506
+ -- test spi_prepare
507
+ select tcl_eval('spi_prepare');
508
+ ERROR: wrong # args: should be "spi_prepare query argtypes"
509
+ select tcl_eval('spi_prepare a b');
510
+ ERROR: type "b" does not exist
511
+ select tcl_eval('spi_prepare a "b {"');
512
+ ERROR: unmatched open brace in list
513
+ select tcl_error_handling_test($tcl$spi_prepare "select moo" []$tcl$);
514
+ tcl_error_handling_test
515
+ --------------------------------------
516
+ SQLSTATE: 42703 +
517
+ condition: undefined_column +
518
+ cursor_position: 8 +
519
+ message: column "moo" does not exist+
520
+ statement: select moo
521
+ (1 row)
522
+
523
+ -- test full error text
524
+ select tcl_error_handling_test($tcl$
525
+ spi_exec "DO $$
526
+ BEGIN
527
+ RAISE 'my message'
528
+ USING HINT = 'my hint'
529
+ , DETAIL = 'my detail'
530
+ , SCHEMA = 'my schema'
531
+ , TABLE = 'my table'
532
+ , COLUMN = 'my column'
533
+ , CONSTRAINT = 'my constraint'
534
+ , DATATYPE = 'my datatype'
535
+ ;
536
+ END$$;"
537
+ $tcl$);
538
+ tcl_error_handling_test
539
+ --------------------------------------------------------------
540
+ SQLSTATE: P0001 +
541
+ column: my column +
542
+ condition: raise_exception +
543
+ constraint: my constraint +
544
+ context: PL/pgSQL function inline_code_block line 3 at RAISE+
545
+ SQL statement "DO $$ +
546
+ BEGIN +
547
+ RAISE 'my message' +
548
+ USING HINT = 'my hint' +
549
+ , DETAIL = 'my detail' +
550
+ , SCHEMA = 'my schema' +
551
+ , TABLE = 'my table' +
552
+ , COLUMN = 'my column' +
553
+ , CONSTRAINT = 'my constraint' +
554
+ , DATATYPE = 'my datatype' +
555
+ ; +
556
+ END$$;" +
557
+ datatype: my datatype +
558
+ detail: my detail +
559
+ hint: my hint +
560
+ message: my message +
561
+ schema: my schema +
562
+ table: my table
563
+ (1 row)
564
+
565
+ -- verify tcl_error_handling_test() properly reports non-postgres errors
566
+ select tcl_error_handling_test('moo');
567
+ tcl_error_handling_test
568
+ ----------------------------
569
+ invalid command name "moo"
570
+ (1 row)
571
+
572
+ -- test elog
573
+ select tcl_eval('elog');
574
+ ERROR: wrong # args: should be "elog level msg"
575
+ select tcl_eval('elog foo bar');
576
+ ERROR: bad priority "foo": must be DEBUG, LOG, INFO, NOTICE, WARNING, ERROR, or FATAL
577
+ -- test forced error
578
+ select tcl_eval('error "forced error"');
579
+ ERROR: forced error
580
+ -- test loop control in spi_exec[p]
581
+ select tcl_spi_exec(true, 'break');
582
+ NOTICE: col1 1, col2 foo
583
+ NOTICE: col1 2, col2 bar
584
+ NOTICE: action: break
585
+ NOTICE: end of function
586
+ tcl_spi_exec
587
+ --------------
588
+
589
+ (1 row)
590
+
591
+ select tcl_spi_exec(true, 'continue');
592
+ NOTICE: col1 1, col2 foo
593
+ NOTICE: col1 2, col2 bar
594
+ NOTICE: action: continue
595
+ NOTICE: col1 3, col2 baz
596
+ NOTICE: end of function
597
+ tcl_spi_exec
598
+ --------------
599
+
600
+ (1 row)
601
+
602
+ select tcl_spi_exec(true, 'error');
603
+ NOTICE: col1 1, col2 foo
604
+ NOTICE: col1 2, col2 bar
605
+ NOTICE: action: error
606
+ ERROR: error message
607
+ select tcl_spi_exec(true, 'return');
608
+ NOTICE: col1 1, col2 foo
609
+ NOTICE: col1 2, col2 bar
610
+ NOTICE: action: return
611
+ tcl_spi_exec
612
+ --------------
613
+
614
+ (1 row)
615
+
616
+ select tcl_spi_exec(false, 'break');
617
+ NOTICE: col1 1, col2 foo
618
+ NOTICE: col1 2, col2 bar
619
+ NOTICE: action: break
620
+ NOTICE: end of function
621
+ tcl_spi_exec
622
+ --------------
623
+
624
+ (1 row)
625
+
626
+ select tcl_spi_exec(false, 'continue');
627
+ NOTICE: col1 1, col2 foo
628
+ NOTICE: col1 2, col2 bar
629
+ NOTICE: action: continue
630
+ NOTICE: col1 3, col2 baz
631
+ NOTICE: end of function
632
+ tcl_spi_exec
633
+ --------------
634
+
635
+ (1 row)
636
+
637
+ select tcl_spi_exec(false, 'error');
638
+ NOTICE: col1 1, col2 foo
639
+ NOTICE: col1 2, col2 bar
640
+ NOTICE: action: error
641
+ ERROR: error message
642
+ select tcl_spi_exec(false, 'return');
643
+ NOTICE: col1 1, col2 foo
644
+ NOTICE: col1 2, col2 bar
645
+ NOTICE: action: return
646
+ tcl_spi_exec
647
+ --------------
648
+
649
+ (1 row)
650
+
651
+ -- forcibly run the Tcl event loop for awhile, to check that we have not
652
+ -- messed things up too badly by disabling the Tcl notifier subsystem
653
+ select tcl_eval($$
654
+ unset -nocomplain ::tcl_vwait
655
+ after 100 {set ::tcl_vwait 1}
656
+ vwait ::tcl_vwait
657
+ unset -nocomplain ::tcl_vwait$$);
658
+ tcl_eval
659
+ ----------
660
+
661
+ (1 row)
662
+
0 commit comments