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
|
-- CREATE FUNCTION
CREATE FUNCTION plv8_test(keys text[], vals text[]) RETURNS text AS
$$
var o = {};
for (var i = 0; i < keys.length; i++)
o[keys[i]] = vals[i];
return JSON.stringify(o);
$$
LANGUAGE plv8 IMMUTABLE STRICT;
SELECT plv8_test(ARRAY['name', 'age'], ARRAY['Tom', '29']);
plv8_test
---------------------------
{"name":"Tom","age":"29"}
(1 row)
CREATE FUNCTION unnamed_args(text[], text[]) RETURNS text[] AS
$$
var array1 = arguments[0];
var array2 = $2;
return array1.concat(array2);
$$
LANGUAGE plv8 IMMUTABLE STRICT;
SELECT unnamed_args(ARRAY['A', 'B'], ARRAY['C', 'D']);
unnamed_args
--------------
{A,B,C,D}
(1 row)
CREATE FUNCTION concat_strings(VARIADIC args text[]) RETURNS text AS
$$
var result = "";
for (var i = 0; i < args.length; i++)
if (args[i] != null)
result += args[i];
return result;
$$
LANGUAGE plv8 IMMUTABLE STRICT;
SELECT concat_strings('A', 'B', NULL, 'C');
concat_strings
----------------
ABC
(1 row)
CREATE FUNCTION return_void() RETURNS void AS $$ $$ LANGUAGE plv8;
SELECT return_void();
return_void
-------------
(1 row)
CREATE FUNCTION return_null() RETURNS text AS $$ return null; $$ LANGUAGE plv8;
SELECT r, r IS NULL AS isnull FROM return_null() AS r;
r | isnull
---+--------
| t
(1 row)
-- TYPE CONVERTIONS
CREATE FUNCTION int2_to_int4(x int2) RETURNS int4 AS $$ return x; $$ LANGUAGE plv8;
SELECT int2_to_int4(24::int2);
int2_to_int4
--------------
24
(1 row)
CREATE FUNCTION int4_to_int2(x int4) RETURNS int2 AS $$ return x; $$ LANGUAGE plv8;
SELECT int4_to_int2(42);
int4_to_int2
--------------
42
(1 row)
CREATE FUNCTION int4_to_int8(x int4) RETURNS int8 AS $$ return x; $$ LANGUAGE plv8;
SELECT int4_to_int8(48);
int4_to_int8
--------------
48
(1 row)
CREATE FUNCTION int8_to_int4(x int8) RETURNS int4 AS $$ return x; $$ LANGUAGE plv8;
SELECT int8_to_int4(84);
int8_to_int4
--------------
84
(1 row)
CREATE FUNCTION float8_to_numeric(x float8) RETURNS numeric AS $$ return x; $$ LANGUAGE plv8;
SELECT float8_to_numeric(1.5);
float8_to_numeric
-------------------
1.5
(1 row)
CREATE FUNCTION numeric_to_int8(x numeric) RETURNS int8 AS $$ return x; $$ LANGUAGE plv8;
SELECT numeric_to_int8(1234.56);
numeric_to_int8
-----------------
1234
(1 row)
CREATE FUNCTION int4_to_text(x int4) RETURNS text AS $$ return x; $$ LANGUAGE plv8;
SELECT int4_to_text(123);
int4_to_text
--------------
123
(1 row)
CREATE FUNCTION text_to_int4(x text) RETURNS int4 AS $$ return x; $$ LANGUAGE plv8;
SELECT text_to_int4('123');
text_to_int4
--------------
123
(1 row)
SELECT text_to_int4('abc'); -- error
ERROR: invalid input syntax for integer: "abc"
CREATE FUNCTION int4array_to_textarray(x int4[]) RETURNS text[] AS $$ return x; $$ LANGUAGE plv8;
SELECT int4array_to_textarray(ARRAY[123, 456]::int4[]);
int4array_to_textarray
------------------------
{123,456}
(1 row)
CREATE FUNCTION textarray_to_int4array(x text[]) RETURNS int4[] AS $$ return x; $$ LANGUAGE plv8;
SELECT textarray_to_int4array(ARRAY['123', '456']::text[]);
textarray_to_int4array
------------------------
{123,456}
(1 row)
CREATE FUNCTION timestamptz_to_text(t timestamptz) RETURNS text AS $$ return t.toUTCString() $$ LANGUAGE plv8;
SELECT timestamptz_to_text('23 Dec 2010 12:34:56 GMT');
timestamptz_to_text
-------------------------------
Thu, 23 Dec 2010 12:34:56 GMT
(1 row)
CREATE FUNCTION text_to_timestamptz(t text) RETURNS timestamptz AS $$ return new Date(t) $$ LANGUAGE plv8;
SELECT text_to_timestamptz('23 Dec 2010 12:34:56 GMT') AT TIME ZONE 'GMT';
timezone
--------------------------
Thu Dec 23 12:34:56 2010
(1 row)
CREATE FUNCTION date_to_text(t date) RETURNS text AS $$ return t.toUTCString() $$ LANGUAGE plv8;
SELECT date_to_text('23 Dec 2010');
date_to_text
-------------------------------
Thu, 23 Dec 2010 00:00:00 GMT
(1 row)
CREATE FUNCTION text_to_date(t text) RETURNS date AS $$ return new Date(t) $$ LANGUAGE plv8;
SELECT text_to_date('23 Dec 2010 GMT');
text_to_date
--------------
12-23-2010
(1 row)
CREATE FUNCTION oidfn(id oid) RETURNS oid AS $$ return id $$ LANGUAGE plv8;
SELECT oidfn('pg_catalog.pg_class'::regclass);
oidfn
-------
1259
(1 row)
-- RECORD TYPES
CREATE TYPE rec AS (i integer, t text);
CREATE FUNCTION scalar_to_record(i integer, t text) RETURNS rec AS
$$
return { "i": i, "t": t };
$$
LANGUAGE plv8;
SELECT scalar_to_record(1, 'a');
scalar_to_record
------------------
(1,a)
(1 row)
CREATE FUNCTION record_to_text(x rec) RETURNS text AS
$$
return JSON.stringify(x);
$$
LANGUAGE plv8;
SELECT record_to_text('(1,a)'::rec);
record_to_text
-----------------
{"i":1,"t":"a"}
(1 row)
CREATE FUNCTION return_record(i integer, t text) RETURNS record AS
$$
return { "i": i, "t": t };
$$
LANGUAGE plv8;
SELECT * FROM return_record(1, 'a');
ERROR: a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM return_record(1, 'a');
^
SELECT * FROM return_record(1, 'a') AS t(j integer, s text);
ERROR: input of anonymous composite types is not implemented
SELECT * FROM return_record(1, 'a') AS t(x text, y text);
ERROR: input of anonymous composite types is not implemented
CREATE FUNCTION set_of_records() RETURNS SETOF rec AS
$$
plv8.return_next( { "i": 1, "t": "a" } );
plv8.return_next( { "i": 2, "t": "b" } );
plv8.return_next( { "i": 3, "t": "c" } );
$$
LANGUAGE plv8;
SELECT * FROM set_of_records();
i | t
---+---
1 | a
2 | b
3 | c
(3 rows)
CREATE FUNCTION set_of_record_but_non_obj() RETURNS SETOF rec AS
$$
plv8.return_next( "abc" );
$$
LANGUAGE plv8;
SELECT * FROM set_of_record_but_non_obj();
ERROR: Error: argument must be an object
DETAIL: set_of_record_but_non_obj() LINE 2: plv8.return_next( "abc" );
CREATE FUNCTION set_of_integers() RETURNS SETOF integer AS
$$
plv8.return_next( 1 );
plv8.return_next( 2 );
plv8.return_next( 3 );
$$
LANGUAGE plv8;
SELECT * FROM set_of_integers();
set_of_integers
-----------------
1
2
3
(3 rows)
CREATE FUNCTION set_of_nest() RETURNS SETOF float AS
$$
plv8.return_next( -0.2 );
var rows = plv8.execute( "SELECT set_of_integers() AS i" );
plv8.return_next( rows[0].i );
return 0.2;
$$
LANGUAGE plv8;
SELECT * FROM set_of_nest();
set_of_nest
-------------
-0.2
1
0.2
(3 rows)
CREATE FUNCTION set_of_unnamed_records() RETURNS SETOF record AS
$$
return [ { i: true } ];
$$
LANGUAGE plv8;
SELECT set_of_unnamed_records();
ERROR: function returning record called in context that cannot accept type record
SELECT * FROM set_of_unnamed_records() t (i bool);
i
---
t
(1 row)
CREATE OR REPLACE FUNCTION set_of_unnamed_records() RETURNS SETOF record AS
$$
plv8.return_next({"a": 1, "b": 2});
return;
$$ LANGUAGE plv8;
-- not enough fields specified
SELECT * FROM set_of_unnamed_records() AS x(a int);
a
---
1
(1 row)
-- field names mismatch
SELECT * FROM set_of_unnamed_records() AS x(a int, c int);
ERROR: Error: field name / property name mismatch
DETAIL: set_of_unnamed_records() LINE 2: plv8.return_next({"a": 1, "b": 2});
-- name counts and values match
SELECT * FROM set_of_unnamed_records() AS x(a int, b int);
a | b
---+---
1 | 2
(1 row)
-- return type check
CREATE OR REPLACE FUNCTION bogus_return_type() RETURNS int[] AS
$$
return 1;
$$ LANGUAGE plv8;
SELECT bogus_return_type();
ERROR: value is not an Array
-- INOUT and OUT parameters
CREATE FUNCTION one_inout(a integer, INOUT b text) AS
$$
return a + b;
$$
LANGUAGE plv8;
SELECT one_inout(5, 'ABC');
one_inout
-----------
5ABC
(1 row)
CREATE FUNCTION one_out(OUT o text, i integer) AS
$$
return 'ABC' + i;
$$
LANGUAGE plv8;
SELECT one_out(123);
one_out
---------
ABC123
(1 row)
-- polymorphic types
CREATE FUNCTION polymorphic(poly anyarray) returns anyelement AS
$$
return poly[0];
$$
LANGUAGE plv8;
SELECT polymorphic(ARRAY[10, 11]), polymorphic(ARRAY['foo', 'bar']);
polymorphic | polymorphic
-------------+-------------
10 | foo
(1 row)
-- typed array
CREATE FUNCTION fastsum(ary plv8_int4array) RETURNS int8 AS
$$
sum = 0;
for (var i = 0; i < ary.length; i++) {
sum += ary[i];
}
return sum;
$$
LANGUAGE plv8 IMMUTABLE STRICT;
SELECT fastsum(ARRAY[1, 2, 3, 4, 5]);
fastsum
---------
15
(1 row)
SELECT fastsum(ARRAY[NULL, 2]);
ERROR: NULL element, or multi-dimension array not allowed in external array type
-- elog()
CREATE FUNCTION test_elog(arg text) RETURNS void AS
$$
plv8.elog(NOTICE, 'args =', arg);
plv8.elog(WARNING, 'warning');
try{
plv8.elog(ERROR, 'ERROR');
}catch(e){
plv8.elog(INFO, e);
}
plv8.elog(21, 'FATAL is not allowed');
$$
LANGUAGE plv8;
SELECT test_elog('ABC');
NOTICE: args = ABC
WARNING: warning
INFO: Error: ERROR
ERROR: Error: invalid error level
DETAIL: test_elog() LINE 9: plv8.elog(21, 'FATAL is not allowed');
-- execute()
CREATE TABLE test_tbl (i integer, s text);
CREATE FUNCTION test_sql() RETURNS integer AS
$$
// for name[] conversion test, add current_schemas()
var rows = plv8.execute("SELECT i, 's' || i AS s, current_schemas(true) AS c FROM generate_series(1, 4) AS t(i)");
for (var r = 0; r < rows.length; r++)
{
var result = plv8.execute("INSERT INTO test_tbl VALUES(" + rows[r].i + ",'" + rows[r].s + "')");
plv8.elog(NOTICE, JSON.stringify(rows[r]), result);
}
return rows.length;
$$
LANGUAGE plv8;
SELECT test_sql();
NOTICE: {"i":1,"s":"s1","c":["pg_catalog","public"]} 1
NOTICE: {"i":2,"s":"s2","c":["pg_catalog","public"]} 1
NOTICE: {"i":3,"s":"s3","c":["pg_catalog","public"]} 1
NOTICE: {"i":4,"s":"s4","c":["pg_catalog","public"]} 1
test_sql
----------
4
(1 row)
SELECT * FROM test_tbl;
i | s
---+----
1 | s1
2 | s2
3 | s3
4 | s4
(4 rows)
CREATE FUNCTION return_sql() RETURNS SETOF test_tbl AS
$$
return plv8.execute(
"SELECT i, $1 || i AS s FROM generate_series(1, $2) AS t(i)",
[ 's', 4 ]
);
$$
LANGUAGE plv8;
SELECT * FROM return_sql();
i | s
---+----
1 | s1
2 | s2
3 | s3
4 | s4
(4 rows)
CREATE FUNCTION test_sql_error() RETURNS void AS $$ plv8.execute("ERROR") $$ LANGUAGE plv8;
SELECT test_sql_error();
ERROR: Error: syntax error at or near "ERROR"
DETAIL: test_sql_error() LINE 1: plv8.execute("ERROR")
CREATE FUNCTION catch_sql_error() RETURNS void AS $$
try {
plv8.execute("throw SQL error");
plv8.elog(NOTICE, "should not come here");
} catch (e) {
plv8.elog(NOTICE, e);
}
$$ LANGUAGE plv8;
SELECT catch_sql_error();
NOTICE: Error: syntax error at or near "throw"
catch_sql_error
-----------------
(1 row)
CREATE FUNCTION catch_sql_error_2() RETURNS text AS $$
try {
plv8.execute("throw SQL error");
plv8.elog(NOTICE, "should not come here");
} catch (e) {
plv8.elog(NOTICE, e);
return plv8.execute("select 'and can execute queries again' t").shift().t;
}
$$ LANGUAGE plv8;
SELECT catch_sql_error_2();
NOTICE: Error: syntax error at or near "throw"
catch_sql_error_2
-------------------------------
and can execute queries again
(1 row)
-- subtransaction()
CREATE TABLE subtrant(a int);
CREATE FUNCTION test_subtransaction_catch() RETURNS void AS $$
try {
plv8.subtransaction(function(){
plv8.execute("INSERT INTO subtrant VALUES(1)");
plv8.execute("INSERT INTO subtrant VALUES(1/0)");
});
} catch (e) {
plv8.elog(NOTICE, e);
plv8.execute("INSERT INTO subtrant VALUES(2)");
}
$$ LANGUAGE plv8;
SELECT test_subtransaction_catch();
NOTICE: Error: division by zero
test_subtransaction_catch
---------------------------
(1 row)
SELECT * FROM subtrant;
a
---
2
(1 row)
TRUNCATE subtrant;
CREATE FUNCTION test_subtransaction_throw() RETURNS void AS $$
plv8.subtransaction(function(){
plv8.execute("INSERT INTO subtrant VALUES(1)");
plv8.execute("INSERT INTO subtrant VALUES(1/0)");
});
$$ LANGUAGE plv8;
SELECT test_subtransaction_throw();
ERROR: Error: division by zero
DETAIL: test_subtransaction_throw() LINE 2: plv8.subtransaction(function(){
SELECT * FROM subtrant;
a
---
(0 rows)
-- REPLACE FUNCTION
CREATE FUNCTION replace_test() RETURNS integer AS $$ return 1; $$ LANGUAGE plv8;
SELECT replace_test();
replace_test
--------------
1
(1 row)
CREATE OR REPLACE FUNCTION replace_test() RETURNS integer AS $$ return 2; $$ LANGUAGE plv8;
SELECT replace_test();
replace_test
--------------
2
(1 row)
-- TRIGGER
CREATE FUNCTION test_trigger() RETURNS trigger AS
$$
plv8.elog(NOTICE, "NEW = ", JSON.stringify(NEW));
plv8.elog(NOTICE, "OLD = ", JSON.stringify(OLD));
plv8.elog(NOTICE, "TG_OP = ", TG_OP);
plv8.elog(NOTICE, "TG_ARGV = ", TG_ARGV);
if (TG_OP == "UPDATE") {
NEW.i = 102;
return NEW;
}
$$
LANGUAGE "plv8";
CREATE TRIGGER test_trigger
BEFORE INSERT OR UPDATE OR DELETE
ON test_tbl FOR EACH ROW
EXECUTE PROCEDURE test_trigger('foo', 'bar');
INSERT INTO test_tbl VALUES(100, 'ABC');
NOTICE: NEW = {"i":100,"s":"ABC"}
NOTICE: OLD = undefined
NOTICE: TG_OP = INSERT
NOTICE: TG_ARGV = foo,bar
UPDATE test_tbl SET i = 101, s = 'DEF' WHERE i = 1;
NOTICE: NEW = {"i":101,"s":"DEF"}
NOTICE: OLD = {"i":1,"s":"s1"}
NOTICE: TG_OP = UPDATE
NOTICE: TG_ARGV = foo,bar
DELETE FROM test_tbl WHERE i >= 100;
NOTICE: NEW = undefined
NOTICE: OLD = {"i":100,"s":"ABC"}
NOTICE: TG_OP = DELETE
NOTICE: TG_ARGV = foo,bar
NOTICE: NEW = undefined
NOTICE: OLD = {"i":102,"s":"DEF"}
NOTICE: TG_OP = DELETE
NOTICE: TG_ARGV = foo,bar
SELECT * FROM test_tbl;
i | s
---+----
2 | s2
3 | s3
4 | s4
(3 rows)
-- One more trigger
CREATE FUNCTION test_trigger2() RETURNS trigger AS
$$
var tuple;
switch (TG_OP) {
case "INSERT":
tuple = NEW;
break;
case "UPDATE":
tuple = OLD;
break;
case "DELETE":
tuple = OLD;
break;
default:
return;
}
if (tuple.subject == "skip") {
return null;
}
if (tuple.subject == "modify" && NEW) {
NEW.val = tuple.val * 2;
return NEW;
}
$$
LANGUAGE "plv8";
CREATE TABLE trig_table (subject text, val int);
INSERT INTO trig_table VALUES('skip', 1);
CREATE TRIGGER test_trigger2
BEFORE INSERT OR UPDATE OR DELETE
ON trig_table FOR EACH ROW
EXECUTE PROCEDURE test_trigger2();
INSERT INTO trig_table VALUES
('skip', 1), ('modify', 2), ('noop', 3);
SELECT * FROM trig_table;
subject | val
---------+-----
skip | 1
modify | 4
noop | 3
(3 rows)
UPDATE trig_table SET val = 10;
SELECT * FROM trig_table;
subject | val
---------+-----
skip | 1
modify | 8
noop | 10
(3 rows)
DELETE FROM trig_table;
SELECT * FROM trig_table;
subject | val
---------+-----
skip | 1
(1 row)
-- ERRORS
CREATE FUNCTION syntax_error() RETURNS text AS '@' LANGUAGE plv8;
ERROR: SyntaxError: Unexpected token ILLEGAL
DETAIL: syntax_error() LINE 1: @
CREATE FUNCTION reference_error() RETURNS text AS 'not_defined' LANGUAGE plv8;
SELECT reference_error();
ERROR: ReferenceError: not_defined is not defined
DETAIL: reference_error() LINE 1: not_defined
CREATE FUNCTION throw() RETURNS void AS $$throw new Error("an error");$$ LANGUAGE plv8;
SELECT throw();
ERROR: Error: an error
DETAIL: throw() LINE 1: throw new Error("an error");
-- SPI operations
CREATE FUNCTION prep1() RETURNS void AS $$
var plan = plv8.prepare("SELECT * FROM test_tbl");
plv8.elog(INFO, plan.toString());
var rows = plan.execute();
for(var i = 0; i < rows.length; i++) {
plv8.elog(INFO, JSON.stringify(rows[i]));
}
var cursor = plan.cursor();
plv8.elog(INFO, cursor.toString());
var row;
while(row = cursor.fetch()) {
plv8.elog(INFO, JSON.stringify(row));
}
cursor.close();
var cursor = plan.cursor();
var rows;
rows = cursor.fetch(2);
plv8.elog(INFO, JSON.stringify(rows));
rows = cursor.fetch(-2);
plv8.elog(INFO, JSON.stringify(rows));
cursor.move(1);
rows = cursor.fetch(3);
plv8.elog(INFO, JSON.stringify(rows));
cursor.move(-2);
rows = cursor.fetch(3);
plv8.elog(INFO, JSON.stringify(rows));
cursor.close();
plan.free();
var plan = plv8.prepare("SELECT * FROM test_tbl WHERE i = $1 and s = $2", ["int", "text"]);
var rows = plan.execute([2, "s2"]);
plv8.elog(INFO, "rows.length = ", rows.length);
var cursor = plan.cursor([2, "s2"]);
plv8.elog(INFO, JSON.stringify(cursor.fetch()));
cursor.close();
plan.free();
try{
var plan = plv8.prepare("SELECT * FROM test_tbl");
plan.free();
plan.execute();
}catch(e){
plv8.elog(WARNING, e);
}
try{
var plan = plv8.prepare("SELECT * FROM test_tbl");
var cursor = plan.cursor();
cursor.close();
cursor.fetch();
}catch(e){
plv8.elog(WARNING, e);
}
$$ LANGUAGE plv8 STRICT;
SELECT prep1();
INFO: [object PreparedPlan]
INFO: {"i":2,"s":"s2"}
INFO: {"i":3,"s":"s3"}
INFO: {"i":4,"s":"s4"}
INFO: [object Cursor]
INFO: {"i":2,"s":"s2"}
INFO: {"i":3,"s":"s3"}
INFO: {"i":4,"s":"s4"}
INFO: [{"i":2,"s":"s2"},{"i":3,"s":"s3"}]
INFO: [{"i":2,"s":"s2"}]
INFO: [{"i":3,"s":"s3"},{"i":4,"s":"s4"}]
INFO: [{"i":4,"s":"s4"}]
INFO: rows.length = 1
INFO: {"i":2,"s":"s2"}
WARNING: Error: plan expected -1 argument(s), given is 0
WARNING: Error: cannot find cursor
prep1
-------
(1 row)
-- find_function
CREATE FUNCTION callee(a int) RETURNS int AS $$ return a * a $$ LANGUAGE plv8;
CREATE FUNCTION sqlf(int) RETURNS int AS $$ SELECT $1 * $1 $$ LANGUAGE sql;
CREATE FUNCTION caller(a int, t int) RETURNS int AS $$
var func;
if (t == 1) {
func = plv8.find_function("callee");
} else if (t == 2) {
func = plv8.find_function("callee(int)");
} else if (t == 3) {
func = plv8.find_function("sqlf");
} else if (t == 4) {
func = plv8.find_function("callee(int, int)");
} else if (t == 5) {
try{
func = plv8.find_function("caller()");
}catch(e){
func = function(a){ return a };
}
}
return func(a);
$$ LANGUAGE plv8;
SELECT caller(10, 1);
caller
--------
100
(1 row)
SELECT caller(10, 2);
caller
--------
100
(1 row)
SELECT caller(10, 3);
ERROR: Error: javascript function is not found for "sqlf"
DETAIL: caller() LINE 8: func = plv8.find_function("sqlf");
SELECT caller(10, 4);
ERROR: Error: function "callee(int, int)" does not exist
DETAIL: caller() LINE 10: func = plv8.find_function("callee(int, int)");
SELECT caller(10, 5);
caller
--------
10
(1 row)
-- quote_*
CREATE FUNCTION plv8_quotes(s text) RETURNS text AS $$
return [plv8.quote_literal(s), plv8.quote_nullable(s), plv8.quote_ident(s)].join(":");
$$ LANGUAGE plv8 IMMUTABLE;
SELECT plv8_quotes('select');
plv8_quotes
----------------------------
'select':'select':"select"
(1 row)
SELECT plv8_quotes('kevin''s name');
plv8_quotes
------------------------------------------------
'kevin''s name':'kevin''s name':"kevin's name"
(1 row)
SELECT plv8_quotes(NULL);
plv8_quotes
--------------------
'null':NULL:"null"
(1 row)
DROP TABLE IF EXISTS t_attdrop CASCADE;
NOTICE: table "t_attdrop" does not exist, skipping
CREATE TABLE t_attdrop AS SELECT i a, i b, i c FROM generate_series(1, 10)i;
CREATE OR REPLACE FUNCTION f_attdrop(tbl t_attdrop) RETURNS int AS $$
return tbl.a;
$$ LANGUAGE plv8;
CREATE OR REPLACE FUNCTION f_attdrop(a int) RETURNS t_attdrop AS $$
return {a: a, b: 0, c: 10};
$$ LANGUAGE plv8;
ALTER TABLE t_attdrop DROP COLUMN b;
SELECT f_attdrop(t.*) FROM t;
ERROR: relation "t" does not exist
LINE 1: SELECT f_attdrop(t.*) FROM t;
^
SELECT f_attdrop(2);
f_attdrop
-----------
(2,10)
(1 row)
create table plv8test ( id serial primary key, data json, sum integer, num integer);
insert into plv8test (data, sum, num) values ('{"a": 1, "b": 2}', 0, 0);
insert into plv8test (data, sum, num) values ('{"a": 3, "b": 4}', 0, 0);
insert into plv8test (data, sum, num) values ('{"a": 3, "b": 4}', 0, 0);
CREATE OR REPLACE FUNCTION plv8_trigger_handler() RETURNS trigger AS
$$
var sum = 0;
for (var k in NEW.data){ sum += NEW.data[k];}
NEW.sum = sum
return NEW;
$$
LANGUAGE plv8;
CREATE TRIGGER plv8test_trigger
BEFORE INSERT OR UPDATE
ON plv8test FOR EACH ROW
EXECUTE PROCEDURE plv8_trigger_handler();
-- test OK
update plv8test set num = 2 where id =2;
-- then add two fields and drop one of them
alter table plv8test add column repro1 varchar;
alter table plv8test add column repro2 varchar;
alter table plv8test drop column repro1;
-- dropped columns should work with trigger
update plv8test set repro2='test';
|