|
27 | 27 | import static java.util.stream.Collectors.toList; |
28 | 28 |
|
29 | 29 | import org.postgresql.pljava.PLJavaBasedLanguage.InlineBlocks; |
| 30 | +import org.postgresql.pljava.PLJavaBasedLanguage.ReturningSets; |
30 | 31 | import org.postgresql.pljava.PLJavaBasedLanguage.Routines; |
31 | 32 | import org.postgresql.pljava.PLJavaBasedLanguage.Routine; |
32 | 33 | import org.postgresql.pljava.PLJavaBasedLanguage.Template; |
|
180 | 181 | " TRANSFORM FOR TYPE line, FOR TYPE box, FOR TYPE lseg" + |
181 | 182 | " LANGUAGE glot64 AS 'SSBjb3VsZCB1c2UgdHJhbnNmb3JtcyEK'", |
182 | 183 |
|
183 | | -"SELECT javatest.usingtransforms()" |
| 184 | +"SELECT javatest.usingtransforms()", |
| 185 | + |
| 186 | +"CREATE FUNCTION setof3() RETURNS SETOF INT" + |
| 187 | +" LANGUAGE glot64 AS 'Mw==' /* 3 */", |
| 188 | + |
| 189 | +"SELECT javatest.setof3() LIMIT 2" |
184 | 190 | }, remove = { |
| 191 | +"DROP FUNCTION javatest.setof3()", |
185 | 192 | "DROP FUNCTION javatest.usingtransforms()", |
186 | 193 | "DROP TRANSFORM FOR lseg LANGUAGE glot64", |
187 | 194 | "DROP TRANSFORM FOR box LANGUAGE glot64", |
|
202 | 209 | "DROP LANGUAGE glot64", |
203 | 210 | "DROP FUNCTION javatest.glot64_validator(oid)" |
204 | 211 | }) |
205 | | -public class Glot64 implements InlineBlocks, Routines, Triggers, UsingTransforms |
| 212 | +public class Glot64 |
| 213 | +implements InlineBlocks, Routines, ReturningSets, Triggers, UsingTransforms |
206 | 214 | { |
207 | 215 | private final ProceduralLanguage pl; |
208 | 216 |
|
@@ -309,7 +317,21 @@ public void additionalChecks( |
309 | 317 | * and has no interaction with database state, so the judgment call can |
310 | 318 | * be made (as here) to include this check even when checkBody is false. |
311 | 319 | */ |
312 | | - compile(subject.src()); |
| 320 | + String compiled = compile(subject.src()); |
| 321 | + |
| 322 | + if ( subject.returnsSet() ) |
| 323 | + { |
| 324 | + try |
| 325 | + { |
| 326 | + Integer.parseInt(compiled); |
| 327 | + } |
| 328 | + catch ( NumberFormatException e ) |
| 329 | + { |
| 330 | + throw new SQLSyntaxErrorException( |
| 331 | + "the body of a Glot64 set-returning function must compile" + |
| 332 | + " to an integer", "42P13", e); |
| 333 | + } |
| 334 | + } |
313 | 335 |
|
314 | 336 | System.out.printf("ok\n"); |
315 | 337 | } |
@@ -527,6 +549,52 @@ public Template prepare(RegProcedure<?> target, PLJavaBased memo) |
527 | 549 | }; |
528 | 550 | } |
529 | 551 |
|
| 552 | + /** |
| 553 | + * Prepares a template for a set-returning Glot64 function. |
| 554 | + *<p> |
| 555 | + * The source of any set-returning Glot64 function must "compile" to |
| 556 | + * the string representation of an integer. |
| 557 | + *<p> |
| 558 | + * The generated routine will ignore any arguments, and produce a number of |
| 559 | + * rows (of, for now, nothing, as {@code TupleTableSlot} isn't writable yet) |
| 560 | + * equal to the integer. If the integer is negative, the return of a single |
| 561 | + * (non-set) result is exercised. |
| 562 | + */ |
| 563 | + @Override |
| 564 | + public SRFTemplate prepareSRF(RegProcedure<?> target, PLJavaBased memo) |
| 565 | + throws SQLException |
| 566 | + { |
| 567 | + int rowsToReturn = Integer.parseInt(compile(target.src())); |
| 568 | + |
| 569 | + return (SRFTemplate.ValuePerCall) flinfo -> |
| 570 | + { |
| 571 | + return fcinfo -> |
| 572 | + { |
| 573 | + return new SRFNext() |
| 574 | + { |
| 575 | + private int rowsLeft = rowsToReturn; |
| 576 | + |
| 577 | + @Override |
| 578 | + public void close() |
| 579 | + { |
| 580 | + System.out.println("ValuePerCall result closed"); |
| 581 | + } |
| 582 | + |
| 583 | + @Override |
| 584 | + public SRFNext.Result nextResult(Call fcinfo) |
| 585 | + { |
| 586 | + if ( 0 > rowsLeft ) |
| 587 | + return SRFNext.Result.SINGLE; |
| 588 | + if ( 0 == rowsLeft ) |
| 589 | + return SRFNext.Result.END; |
| 590 | + -- rowsLeft; |
| 591 | + return SRFNext.Result.MULTIPLE; |
| 592 | + } |
| 593 | + }; |
| 594 | + }; |
| 595 | + }; |
| 596 | + } |
| 597 | + |
530 | 598 | @Override |
531 | 599 | public void essentialTriggerChecks( |
532 | 600 | RegProcedure<ForTrigger> subject, PLJavaBased memo, boolean checkBody) |
|
0 commit comments