PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pl/plperl/sql/plperl.sql

https://gitlab.com/kush/jarulraj-postgresql-cpp
SQL | 474 lines | 321 code | 99 blank | 54 comment | 7 complexity | 0afa80a2d7120e15a717e5ade97c25cc MD5 | raw file
  1. --
  2. -- Test result value processing
  3. --
  4. CREATE OR REPLACE FUNCTION perl_int(int) RETURNS INTEGER AS $$
  5. return undef;
  6. $$ LANGUAGE plperl;
  7. SELECT perl_int(11);
  8. SELECT * FROM perl_int(42);
  9. CREATE OR REPLACE FUNCTION perl_int(int) RETURNS INTEGER AS $$
  10. return $_[0] + 1;
  11. $$ LANGUAGE plperl;
  12. SELECT perl_int(11);
  13. SELECT * FROM perl_int(42);
  14. CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
  15. return undef;
  16. $$ LANGUAGE plperl;
  17. SELECT perl_set_int(5);
  18. SELECT * FROM perl_set_int(5);
  19. CREATE OR REPLACE FUNCTION perl_set_int(int) RETURNS SETOF INTEGER AS $$
  20. return [0..$_[0]];
  21. $$ LANGUAGE plperl;
  22. SELECT perl_set_int(5);
  23. SELECT * FROM perl_set_int(5);
  24. CREATE TYPE testnestperl AS (f5 integer[]);
  25. CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text, f4 testnestperl);
  26. CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
  27. return undef;
  28. $$ LANGUAGE plperl;
  29. SELECT perl_row();
  30. SELECT * FROM perl_row();
  31. CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
  32. return {f2 => 'hello', f1 => 1, f3 => 'world', 'f4' => { 'f5' => [[1]] } };
  33. $$ LANGUAGE plperl;
  34. SELECT perl_row();
  35. SELECT * FROM perl_row();
  36. -- test returning a composite literal
  37. CREATE OR REPLACE FUNCTION perl_row_lit() RETURNS testrowperl AS $$
  38. return '(1,hello,world,"({{1}})")';
  39. $$ LANGUAGE plperl;
  40. SELECT perl_row_lit();
  41. CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
  42. return undef;
  43. $$ LANGUAGE plperl;
  44. SELECT perl_set();
  45. SELECT * FROM perl_set();
  46. CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
  47. return [
  48. { f1 => 1, f2 => 'Hello', f3 => 'World' },
  49. undef,
  50. { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => {} },
  51. { f1 => 4, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => { 'f5' => undef }},
  52. { f1 => 5, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => { 'f5' => '{1}' }},
  53. { f1 => 6, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => { 'f5' => [1] }},
  54. ];
  55. $$ LANGUAGE plperl;
  56. SELECT perl_set();
  57. SELECT * FROM perl_set();
  58. CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$
  59. return [
  60. { f1 => 1, f2 => 'Hello', f3 => 'World' },
  61. { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL', 'f4' => undef },
  62. { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => {} },
  63. { f1 => 4, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => { 'f5' => undef }},
  64. { f1 => 5, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => { 'f5' => '{1}' }},
  65. { f1 => 6, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => { 'f5' => [1] }},
  66. { f1 => 7, f2 => 'Hello', f3 => 'PL/Perl', 'f4' => '({1})' },
  67. ];
  68. $$ LANGUAGE plperl;
  69. SELECT perl_set();
  70. SELECT * FROM perl_set();
  71. CREATE OR REPLACE FUNCTION perl_record() RETURNS record AS $$
  72. return undef;
  73. $$ LANGUAGE plperl;
  74. SELECT perl_record();
  75. SELECT * FROM perl_record();
  76. SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text, f4 testnestperl);
  77. CREATE OR REPLACE FUNCTION perl_record() RETURNS record AS $$
  78. return {f2 => 'hello', f1 => 1, f3 => 'world', 'f4' => { 'f5' => [1] } };
  79. $$ LANGUAGE plperl;
  80. SELECT perl_record();
  81. SELECT * FROM perl_record();
  82. SELECT * FROM perl_record() AS (f1 integer, f2 text, f3 text, f4 testnestperl);
  83. CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
  84. return undef;
  85. $$ LANGUAGE plperl;
  86. SELECT perl_record_set();
  87. SELECT * FROM perl_record_set();
  88. SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
  89. CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
  90. return [
  91. { f1 => 1, f2 => 'Hello', f3 => 'World' },
  92. undef,
  93. { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
  94. ];
  95. $$ LANGUAGE plperl;
  96. SELECT perl_record_set();
  97. SELECT * FROM perl_record_set();
  98. SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
  99. CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$
  100. return [
  101. { f1 => 1, f2 => 'Hello', f3 => 'World' },
  102. { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
  103. { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
  104. ];
  105. $$ LANGUAGE plperl;
  106. SELECT perl_record_set();
  107. SELECT * FROM perl_record_set();
  108. SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text);
  109. CREATE OR REPLACE FUNCTION
  110. perl_out_params(f1 out integer, f2 out text, f3 out text) AS $$
  111. return {f2 => 'hello', f1 => 1, f3 => 'world'};
  112. $$ LANGUAGE plperl;
  113. SELECT perl_out_params();
  114. SELECT * FROM perl_out_params();
  115. SELECT (perl_out_params()).f2;
  116. CREATE OR REPLACE FUNCTION
  117. perl_out_params_set(out f1 integer, out f2 text, out f3 text)
  118. RETURNS SETOF record AS $$
  119. return [
  120. { f1 => 1, f2 => 'Hello', f3 => 'World' },
  121. { f1 => 2, f2 => 'Hello', f3 => 'PostgreSQL' },
  122. { f1 => 3, f2 => 'Hello', f3 => 'PL/Perl' }
  123. ];
  124. $$ LANGUAGE plperl;
  125. SELECT perl_out_params_set();
  126. SELECT * FROM perl_out_params_set();
  127. SELECT (perl_out_params_set()).f3;
  128. --
  129. -- Check behavior with erroneous return values
  130. --
  131. CREATE TYPE footype AS (x INTEGER, y INTEGER);
  132. CREATE OR REPLACE FUNCTION foo_good() RETURNS SETOF footype AS $$
  133. return [
  134. {x => 1, y => 2},
  135. {x => 3, y => 4}
  136. ];
  137. $$ LANGUAGE plperl;
  138. SELECT * FROM foo_good();
  139. CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
  140. return {y => 3, z => 4};
  141. $$ LANGUAGE plperl;
  142. SELECT * FROM foo_bad();
  143. CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
  144. return 42;
  145. $$ LANGUAGE plperl;
  146. SELECT * FROM foo_bad();
  147. CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$
  148. return [
  149. [1, 2],
  150. [3, 4]
  151. ];
  152. $$ LANGUAGE plperl;
  153. SELECT * FROM foo_bad();
  154. CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
  155. return 42;
  156. $$ LANGUAGE plperl;
  157. SELECT * FROM foo_set_bad();
  158. CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
  159. return {y => 3, z => 4};
  160. $$ LANGUAGE plperl;
  161. SELECT * FROM foo_set_bad();
  162. CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
  163. return [
  164. [1, 2],
  165. [3, 4]
  166. ];
  167. $$ LANGUAGE plperl;
  168. SELECT * FROM foo_set_bad();
  169. CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$
  170. return [
  171. {y => 3, z => 4}
  172. ];
  173. $$ LANGUAGE plperl;
  174. SELECT * FROM foo_set_bad();
  175. --
  176. -- Check passing a tuple argument
  177. --
  178. CREATE OR REPLACE FUNCTION perl_get_field(footype, text) RETURNS integer AS $$
  179. return $_[0]->{$_[1]};
  180. $$ LANGUAGE plperl;
  181. SELECT perl_get_field((11,12), 'x');
  182. SELECT perl_get_field((11,12), 'y');
  183. SELECT perl_get_field((11,12), 'z');
  184. --
  185. -- Test return_next
  186. --
  187. CREATE OR REPLACE FUNCTION perl_srf_rn() RETURNS SETOF RECORD AS $$
  188. my $i = 0;
  189. for ("World", "PostgreSQL", "PL/Perl") {
  190. return_next({f1=>++$i, f2=>'Hello', f3=>$_});
  191. }
  192. return;
  193. $$ language plperl;
  194. SELECT * from perl_srf_rn() AS (f1 INTEGER, f2 TEXT, f3 TEXT);
  195. --
  196. -- Test spi_query/spi_fetchrow
  197. --
  198. CREATE OR REPLACE FUNCTION perl_spi_func() RETURNS SETOF INTEGER AS $$
  199. my $x = spi_query("select 1 as a union select 2 as a");
  200. while (defined (my $y = spi_fetchrow($x))) {
  201. return_next($y->{a});
  202. }
  203. return;
  204. $$ LANGUAGE plperl;
  205. SELECT * from perl_spi_func();
  206. --
  207. -- Test spi_fetchrow abort
  208. --
  209. CREATE OR REPLACE FUNCTION perl_spi_func2() RETURNS INTEGER AS $$
  210. my $x = spi_query("select 1 as a union select 2 as a");
  211. spi_cursor_close( $x);
  212. return 0;
  213. $$ LANGUAGE plperl;
  214. SELECT * from perl_spi_func2();
  215. ---
  216. --- Test recursion via SPI
  217. ---
  218. CREATE OR REPLACE FUNCTION recurse(i int) RETURNS SETOF TEXT LANGUAGE plperl
  219. AS $$
  220. my $i = shift;
  221. foreach my $x (1..$i)
  222. {
  223. return_next "hello $x";
  224. }
  225. if ($i > 2)
  226. {
  227. my $z = $i-1;
  228. my $cursor = spi_query("select * from recurse($z)");
  229. while (defined(my $row = spi_fetchrow($cursor)))
  230. {
  231. return_next "recurse $i: $row->{recurse}";
  232. }
  233. }
  234. return undef;
  235. $$;
  236. SELECT * FROM recurse(2);
  237. SELECT * FROM recurse(3);
  238. ---
  239. --- Test array return
  240. ---
  241. CREATE OR REPLACE FUNCTION array_of_text() RETURNS TEXT[][]
  242. LANGUAGE plperl as $$
  243. return [['a"b',undef,'c,d'],['e\\f',undef,'g']];
  244. $$;
  245. SELECT array_of_text();
  246. --
  247. -- Test spi_prepare/spi_exec_prepared/spi_freeplan
  248. --
  249. CREATE OR REPLACE FUNCTION perl_spi_prepared(INTEGER) RETURNS INTEGER AS $$
  250. my $x = spi_prepare('select $1 AS a', 'INTEGER');
  251. my $q = spi_exec_prepared( $x, $_[0] + 1);
  252. spi_freeplan($x);
  253. return $q->{rows}->[0]->{a};
  254. $$ LANGUAGE plperl;
  255. SELECT * from perl_spi_prepared(42);
  256. --
  257. -- Test spi_prepare/spi_query_prepared/spi_freeplan
  258. --
  259. CREATE OR REPLACE FUNCTION perl_spi_prepared_set(INTEGER, INTEGER) RETURNS SETOF INTEGER AS $$
  260. my $x = spi_prepare('SELECT $1 AS a union select $2 as a', 'INT4', 'INT4');
  261. my $q = spi_query_prepared( $x, 1+$_[0], 2+$_[1]);
  262. while (defined (my $y = spi_fetchrow($q))) {
  263. return_next $y->{a};
  264. }
  265. spi_freeplan($x);
  266. return;
  267. $$ LANGUAGE plperl;
  268. SELECT * from perl_spi_prepared_set(1,2);
  269. --
  270. -- Test prepare with a type with spaces
  271. --
  272. CREATE OR REPLACE FUNCTION perl_spi_prepared_double(double precision) RETURNS double precision AS $$
  273. my $x = spi_prepare('SELECT 10.0 * $1 AS a', 'DOUBLE PRECISION');
  274. my $q = spi_query_prepared($x,$_[0]);
  275. my $result;
  276. while (defined (my $y = spi_fetchrow($q))) {
  277. $result = $y->{a};
  278. }
  279. spi_freeplan($x);
  280. return $result;
  281. $$ LANGUAGE plperl;
  282. SELECT perl_spi_prepared_double(4.35) as "double precision";
  283. --
  284. -- Test with a bad type
  285. --
  286. CREATE OR REPLACE FUNCTION perl_spi_prepared_bad(double precision) RETURNS double precision AS $$
  287. my $x = spi_prepare('SELECT 10.0 * $1 AS a', 'does_not_exist');
  288. my $q = spi_query_prepared($x,$_[0]);
  289. my $result;
  290. while (defined (my $y = spi_fetchrow($q))) {
  291. $result = $y->{a};
  292. }
  293. spi_freeplan($x);
  294. return $result;
  295. $$ LANGUAGE plperl;
  296. SELECT perl_spi_prepared_bad(4.35) as "double precision";
  297. -- Test with a row type
  298. CREATE OR REPLACE FUNCTION perl_spi_prepared() RETURNS INTEGER AS $$
  299. my $x = spi_prepare('select $1::footype AS a', 'footype');
  300. my $q = spi_exec_prepared( $x, '(1, 2)');
  301. spi_freeplan($x);
  302. return $q->{rows}->[0]->{a}->{x};
  303. $$ LANGUAGE plperl;
  304. SELECT * from perl_spi_prepared();
  305. CREATE OR REPLACE FUNCTION perl_spi_prepared_row(footype) RETURNS footype AS $$
  306. my $footype = shift;
  307. my $x = spi_prepare('select $1 AS a', 'footype');
  308. my $q = spi_exec_prepared( $x, {}, $footype );
  309. spi_freeplan($x);
  310. return $q->{rows}->[0]->{a};
  311. $$ LANGUAGE plperl;
  312. SELECT * from perl_spi_prepared_row('(1, 2)');
  313. -- simple test of a DO block
  314. DO $$
  315. $a = 'This is a test';
  316. elog(NOTICE, $a);
  317. $$ LANGUAGE plperl;
  318. -- check that restricted operations are rejected in a plperl DO block
  319. DO $$ system("/nonesuch"); $$ LANGUAGE plperl;
  320. DO $$ qx("/nonesuch"); $$ LANGUAGE plperl;
  321. DO $$ open my $fh, "</nonesuch"; $$ LANGUAGE plperl;
  322. -- check that eval is allowed and eval'd restricted ops are caught
  323. DO $$ eval q{chdir '.';}; warn "Caught: $@"; $$ LANGUAGE plperl;
  324. -- check that compiling do (dofile opcode) is allowed
  325. -- but that executing it for a file not already loaded (via require) dies
  326. DO $$ warn do "/dev/null"; $$ LANGUAGE plperl;
  327. -- check that we can't "use" a module that's not been loaded already
  328. -- compile-time error: "Unable to load blib.pm into plperl"
  329. DO $$ use blib; $$ LANGUAGE plperl;
  330. -- check that we can "use" a module that has already been loaded
  331. -- runtime error: "Can't use string ("foo") as a SCALAR ref while "strict refs" in use
  332. DO $do$ use strict; my $name = "foo"; my $ref = $$name; $do$ LANGUAGE plperl;
  333. -- check that we can "use warnings" (in this case to turn a warn into an error)
  334. -- yields "ERROR: Useless use of sort in scalar context."
  335. DO $do$ use warnings FATAL => qw(void) ; my @y; my $x = sort @y; 1; $do$ LANGUAGE plperl;
  336. -- make sure functions marked as VOID without an explicit return work
  337. CREATE OR REPLACE FUNCTION myfuncs() RETURNS void AS $$
  338. $_SHARED{myquote} = sub {
  339. my $arg = shift;
  340. $arg =~ s/(['\\])/\\$1/g;
  341. return "'$arg'";
  342. };
  343. $$ LANGUAGE plperl;
  344. SELECT myfuncs();
  345. -- make sure we can't return an array as a scalar
  346. CREATE OR REPLACE FUNCTION text_arrayref() RETURNS text AS $$
  347. return ['array'];
  348. $$ LANGUAGE plperl;
  349. SELECT text_arrayref();
  350. --- make sure we can't return a hash as a scalar
  351. CREATE OR REPLACE FUNCTION text_hashref() RETURNS text AS $$
  352. return {'hash'=>1};
  353. $$ LANGUAGE plperl;
  354. SELECT text_hashref();
  355. ---- make sure we can't return a blessed object as a scalar
  356. CREATE OR REPLACE FUNCTION text_obj() RETURNS text AS $$
  357. return bless({}, 'Fake::Object');
  358. $$ LANGUAGE plperl;
  359. SELECT text_obj();
  360. ----- make sure we can't return a scalar ref
  361. CREATE OR REPLACE FUNCTION text_scalarref() RETURNS text AS $$
  362. my $str = 'str';
  363. return \$str;
  364. $$ LANGUAGE plperl;
  365. SELECT text_scalarref();
  366. -- check safe behavior when a function body is replaced during execution
  367. CREATE OR REPLACE FUNCTION self_modify(INTEGER) RETURNS INTEGER AS $$
  368. spi_exec_query('CREATE OR REPLACE FUNCTION self_modify(INTEGER) RETURNS INTEGER AS \'return $_[0] * 3;\' LANGUAGE plperl;');
  369. spi_exec_query('select self_modify(42) AS a');
  370. return $_[0] * 2;
  371. $$ LANGUAGE plperl;
  372. SELECT self_modify(42);
  373. SELECT self_modify(42);