Skip to content

Commit ef9ccd7

Browse files
committed
Add set-returning functions to Glot64 toy language
As long as the store direction of TupleTableSlot remains unimplemented, null / void / zero are still the only values any Glot64 function can return. But now it can return sets of them! For a Glot64 set-returning functions, there are stricter limits on the source string. It must be a base64 string that, when 'compiled' (i.e., decoded), is the string representation of a decimal integer. The function so defined will return that many rows (of null / void / zero), ignoring any arguments. If the source string 'compiles' to a negative integer, a single row is returned, exercising the SRFNext.Result.SINGLE case.
1 parent 4c7e5d5 commit ef9ccd7

File tree

1 file changed

+71
-3
lines changed
  • pljava-examples/src/main/java/org/postgresql/pljava/example/polyglot

1 file changed

+71
-3
lines changed

pljava-examples/src/main/java/org/postgresql/pljava/example/polyglot/Glot64.java

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static java.util.stream.Collectors.toList;
2828

2929
import org.postgresql.pljava.PLJavaBasedLanguage.InlineBlocks;
30+
import org.postgresql.pljava.PLJavaBasedLanguage.ReturningSets;
3031
import org.postgresql.pljava.PLJavaBasedLanguage.Routines;
3132
import org.postgresql.pljava.PLJavaBasedLanguage.Routine;
3233
import org.postgresql.pljava.PLJavaBasedLanguage.Template;
@@ -180,8 +181,14 @@
180181
" TRANSFORM FOR TYPE line, FOR TYPE box, FOR TYPE lseg" +
181182
" LANGUAGE glot64 AS 'SSBjb3VsZCB1c2UgdHJhbnNmb3JtcyEK'",
182183

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"
184190
}, remove = {
191+
"DROP FUNCTION javatest.setof3()",
185192
"DROP FUNCTION javatest.usingtransforms()",
186193
"DROP TRANSFORM FOR lseg LANGUAGE glot64",
187194
"DROP TRANSFORM FOR box LANGUAGE glot64",
@@ -202,7 +209,8 @@
202209
"DROP LANGUAGE glot64",
203210
"DROP FUNCTION javatest.glot64_validator(oid)"
204211
})
205-
public class Glot64 implements InlineBlocks, Routines, Triggers, UsingTransforms
212+
public class Glot64
213+
implements InlineBlocks, Routines, ReturningSets, Triggers, UsingTransforms
206214
{
207215
private final ProceduralLanguage pl;
208216

@@ -309,7 +317,21 @@ public void additionalChecks(
309317
* and has no interaction with database state, so the judgment call can
310318
* be made (as here) to include this check even when checkBody is false.
311319
*/
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+
}
313335

314336
System.out.printf("ok\n");
315337
}
@@ -527,6 +549,52 @@ public Template prepare(RegProcedure<?> target, PLJavaBased memo)
527549
};
528550
}
529551

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+
530598
@Override
531599
public void essentialTriggerChecks(
532600
RegProcedure<ForTrigger> subject, PLJavaBased memo, boolean checkBody)

0 commit comments

Comments
 (0)