Skip to content

Commit 9927482

Browse files
committed
[SQL] Forbid non-deterministic SQL UDFs
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
1 parent 1a27866 commit 9927482

File tree

22 files changed

+46
-177
lines changed

22 files changed

+46
-177
lines changed

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/backend/rust/StubsWriter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ DBSPFunction generateStubBody(DBSPFunction function) {
4141
String name = "udf::" + function.name;
4242
List<DBSPExpression> arguments = Linq.map(function.parameters, DBSPParameter::asVariable);
4343
DBSPExpression expression = new DBSPApplyExpression(name, function.returnType, arguments.toArray(new DBSPExpression[0]));
44-
return new DBSPFunction(function.name, function.parameters, function.returnType, expression, function.annotations);
44+
return new DBSPFunction(
45+
function.getNode(), function.name, function.parameters,
46+
function.returnType, expression, function.annotations);
4547
}
4648

4749
@Override

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/backend/rust/ToRustInnerVisitor.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@
125125
import org.dbsp.sqlCompiler.ir.pattern.DBSPIdentifierPattern;
126126
import org.dbsp.sqlCompiler.ir.statement.DBSPComment;
127127
import org.dbsp.sqlCompiler.ir.statement.DBSPComparatorItem;
128-
import org.dbsp.sqlCompiler.ir.statement.DBSPConstItem;
129128
import org.dbsp.sqlCompiler.ir.statement.DBSPExpressionStatement;
130129
import org.dbsp.sqlCompiler.ir.statement.DBSPLetStatement;
131130
import org.dbsp.sqlCompiler.ir.statement.DBSPStatement;
@@ -1770,21 +1769,6 @@ public VisitDecision preorder(DBSPVariablePath expression) {
17701769
return VisitDecision.STOP;
17711770
}
17721771

1773-
@Override
1774-
public VisitDecision preorder(DBSPConstItem item) {
1775-
this.push(item);
1776-
this.builder.append("const ")
1777-
.append(item.name).append(": ");
1778-
item.type.accept(this);
1779-
if (item.expression != null) {
1780-
this.builder.append(" = ");
1781-
item.expression.accept(this);
1782-
}
1783-
this.builder.append(";");
1784-
this.pop(item);
1785-
return VisitDecision.STOP;
1786-
}
1787-
17881772
@Override
17891773
public VisitDecision preorder(DBSPExpressionStatement statement) {
17901774
this.push(statement);

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/frontend/calciteCompiler/ExternalFunction.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public DBSPFunction getDeclaration(TypeCompiler typeCompiler) {
180180
DBSPType returnType = typeCompiler.convertType(this.returnType, false);
181181
// Must wrap the return type in a Result
182182
returnType = new DBSPTypeResult(returnType);
183-
return new DBSPFunction(this.getName(), parameters, returnType, null, Linq.list());
183+
return new DBSPFunction(this.node, this.getName(), parameters, returnType, null, Linq.list());
184184
}
185185

186186
@Nullable
@@ -208,7 +208,7 @@ public DBSPFunction getImplementation(TypeCompiler typeCompiler, DBSPCompiler co
208208
" but returns " + Utilities.singleQuote(this.body.getType().getFullTypeString()), this.node);
209209
}
210210
}
211-
return new DBSPFunction(this.getName(), parameters, returnType, functionBody, Linq.list());
211+
return new DBSPFunction(this.node, this.getName(), parameters, returnType, functionBody, Linq.list());
212212
}
213213
if (!this.generated)
214214
return null;
@@ -247,7 +247,7 @@ public DBSPFunction getImplementation(TypeCompiler typeCompiler, DBSPCompiler co
247247
DBSPExpression body = new DBSPBlockExpression(statements, retval);
248248
// DBSPExpression ok = new DBSPApplyMethodExpression("Ok", new DBSPTypeResult(returnType), retval);
249249
// TODO: the function should return Result
250-
return new DBSPFunction(this.getName(), Linq.list(param), returnType, body, Linq.list());
250+
return new DBSPFunction(this.node, this.getName(), Linq.list(param), returnType, body, Linq.list());
251251
}
252252
throw new InternalCompilerError("Cannot generate implementation for " + this, this.node);
253253
}

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/visitors/inner/ExpressionTranslator.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.dbsp.sqlCompiler.ir.expression.*;
1515
import org.dbsp.sqlCompiler.ir.expression.literal.DBSPLiteral;
1616
import org.dbsp.sqlCompiler.ir.statement.DBSPComment;
17-
import org.dbsp.sqlCompiler.ir.statement.DBSPConstItem;
1817
import org.dbsp.sqlCompiler.ir.statement.DBSPExpressionStatement;
1918
import org.dbsp.sqlCompiler.ir.statement.DBSPFunctionItem;
2019
import org.dbsp.sqlCompiler.ir.statement.DBSPItem;
@@ -256,12 +255,6 @@ public void postorder(DBSPStructItem node) {
256255
this.map(node, node);
257256
}
258257

259-
@Override
260-
public void postorder(DBSPConstItem node) {
261-
DBSPExpression expression = this.getEN(node.expression);
262-
this.map(node, new DBSPConstItem(node.name, node.type, expression));
263-
}
264-
265258
@Override
266259
public void postorder(DBSPIfExpression node) {
267260
DBSPExpression condition = this.getE(node.condition);
@@ -495,7 +488,7 @@ public IDBSPInnerNode apply(IDBSPInnerNode node) {
495488
@Override
496489
public void postorder(DBSPFunction function) {
497490
DBSPExpression body = this.getEN(function.body);
498-
DBSPFunction result = new DBSPFunction(
491+
DBSPFunction result = new DBSPFunction(function.getNode(),
499492
function.name, function.parameters, function.returnType, body, function.annotations);
500493
this.set(function, result);
501494
}

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/visitors/inner/InnerRewriteVisitor.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@
8585
import org.dbsp.sqlCompiler.ir.expression.DBSPArrayExpression;
8686
import org.dbsp.sqlCompiler.ir.expression.DBSPZSetExpression;
8787
import org.dbsp.sqlCompiler.ir.statement.DBSPComment;
88-
import org.dbsp.sqlCompiler.ir.statement.DBSPConstItem;
8988
import org.dbsp.sqlCompiler.ir.statement.DBSPExpressionStatement;
9089
import org.dbsp.sqlCompiler.ir.statement.DBSPFunctionItem;
9190
import org.dbsp.sqlCompiler.ir.statement.DBSPItem;
@@ -127,7 +126,6 @@
127126
import java.util.List;
128127
import java.util.Map;
129128
import java.util.Objects;
130-
import java.util.function.Predicate;
131129

132130
/**
133131
* Base class for Inner visitors which rewrite expressions, types, and statements.
@@ -1322,17 +1320,6 @@ public VisitDecision preorder(DBSPComment comment) {
13221320
return VisitDecision.STOP;
13231321
}
13241322

1325-
@Override
1326-
public VisitDecision preorder(DBSPConstItem item) {
1327-
this.push(item);
1328-
DBSPType type = this.transform(item.type);
1329-
@Nullable DBSPExpression expression = this.transformN(item.expression);
1330-
this.pop(item);
1331-
DBSPConstItem result = new DBSPConstItem(item.name, type, expression);
1332-
this.map(item, result);
1333-
return VisitDecision.STOP;
1334-
}
1335-
13361323
@Override
13371324
public VisitDecision preorder(DBSPFunctionItem item) {
13381325
this.push(item);
@@ -1385,7 +1372,7 @@ public VisitDecision preorder(DBSPFunction function) {
13851372
return Objects.requireNonNull(this.lastResult).to(DBSPParameter.class);
13861373
});
13871374
this.pop(function);
1388-
DBSPFunction result = new DBSPFunction(
1375+
DBSPFunction result = new DBSPFunction(function.getNode(),
13891376
function.name, parameters, returnType, body, function.annotations);
13901377
this.map(function, result);
13911378
return VisitDecision.STOP;

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/visitors/inner/InnerVisitor.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@
7676
import org.dbsp.sqlCompiler.ir.pattern.DBSPPattern;
7777
import org.dbsp.sqlCompiler.ir.statement.DBSPComment;
7878
import org.dbsp.sqlCompiler.ir.statement.DBSPComparatorItem;
79-
import org.dbsp.sqlCompiler.ir.statement.DBSPConstItem;
8079
import org.dbsp.sqlCompiler.ir.statement.DBSPExpressionStatement;
8180
import org.dbsp.sqlCompiler.ir.statement.DBSPFunctionItem;
8281
import org.dbsp.sqlCompiler.ir.statement.DBSPItem;
@@ -327,10 +326,6 @@ public VisitDecision preorder(DBSPLetStatement node) {
327326
return this.preorder((DBSPStatement) node);
328327
}
329328

330-
public VisitDecision preorder(DBSPConstItem node) {
331-
return this.preorder((DBSPItem) node);
332-
}
333-
334329
public VisitDecision preorder(DBSPFunctionItem node) {
335330
return this.preorder((DBSPItem) node);
336331
}
@@ -927,10 +922,6 @@ public void postorder(DBSPItem node) {
927922
this.postorder((DBSPStatement) node);
928923
}
929924

930-
public void postorder(DBSPConstItem node) {
931-
this.postorder((DBSPItem) node);
932-
}
933-
934925
public void postorder(DBSPFunctionItem node) {
935926
this.postorder((DBSPItem) node);
936927
}

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/visitors/outer/CircuitOptimizer.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@
4343
import org.dbsp.sqlCompiler.compiler.visitors.outer.monotonicity.MonotoneAnalyzer;
4444
import org.dbsp.sqlCompiler.ir.IDBSPOuterNode;
4545

46-
/** Very high level circuit-level optimizations.
47-
* Does not really look at the functions inside the circuit. */
46+
/** All optimizations applied to circuits. */
4847
public class CircuitOptimizer extends Passes {
4948
public CircuitOptimizer(DBSPCompiler compiler) {
5049
super("Optimizer", compiler);
@@ -70,7 +69,7 @@ void createOptimizer() {
7069
// this.add(ToDot.dumper(compiler, "x.png", 2));
7170
// First part of optimizations may still synthesize some circuit components
7271
this.add(new ImplementNow(compiler));
73-
this.add(new DeterministicDefault(compiler));
72+
this.add(new DeterministicFunctions(compiler));
7473
this.add(new StopOnError(compiler));
7574
this.add(new RecursiveComponents(compiler));
7675
this.add(new DeadCode(compiler, options.languageOptions.generateInputForEveryTable, true));

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/visitors/outer/DeterministicDefault.java renamed to sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/visitors/outer/DeterministicFunctions.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
import org.dbsp.sqlCompiler.ir.expression.DBSPExpression;
1111
import org.dbsp.sqlCompiler.ir.statement.DBSPFunctionItem;
1212
import org.dbsp.util.Logger;
13+
import org.dbsp.util.Utilities;
1314

1415
import java.util.HashSet;
1516
import java.util.Objects;
1617
import java.util.Set;
1718

18-
/** Check that default values for all column initializers are constant expressions.
19-
* This requires building a call graph. */
20-
public class DeterministicDefault extends CircuitVisitor {
19+
/** Check that no user-defined SQL function calls non-deterministic functions. */
20+
public class DeterministicFunctions extends CircuitVisitor {
2121
final Set<String> nonDeterministic;
2222

2323
static class HasNondeterminism extends InnerVisitor {
@@ -60,7 +60,7 @@ public boolean found() {
6060

6161
final HasNondeterminism hn;
6262

63-
public DeterministicDefault(DBSPCompiler compiler) {
63+
public DeterministicFunctions(DBSPCompiler compiler) {
6464
super(compiler);
6565
this.nonDeterministic = new HashSet<>();
6666
this.markNondeterministic("now");
@@ -97,8 +97,14 @@ public VisitDecision preorder(DBSPDeclaration decl) {
9797
if (function.function.body == null)
9898
return VisitDecision.STOP;
9999
boolean det = this.isDeterministic(function.function.body);
100-
if (!det)
101-
this.markNondeterministic(function.function.getName());
100+
if (!det) {
101+
this.markNondeterministic(decl.getName());
102+
this.compiler.reportError(
103+
Objects.requireNonNull(decl.getSourcePosition()),
104+
"Non-deterministic UDF",
105+
"Non-deterministic user-defined functions are not supported: " +
106+
Utilities.singleQuote(decl.getName()));
107+
}
102108
}
103109
return VisitDecision.STOP;
104110
}

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/ir/DBSPFunction.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ public final class DBSPFunction extends DBSPNode
5454
public final List<String> annotations;
5555
public final DBSPTypeFunction type;
5656

57-
public DBSPFunction(String name, List<DBSPParameter> parameters,
57+
public DBSPFunction(CalciteObject node, String name, List<DBSPParameter> parameters,
5858
DBSPType returnType, @Nullable DBSPExpression body,
5959
List<String> annotations) {
60-
super(CalciteObject.EMPTY);
60+
super(node);
6161
this.name = name;
6262
this.parameters = parameters;
6363
this.returnType = returnType;
@@ -147,6 +147,6 @@ public static DBSPFunction fromJson(JsonNode node, JsonDecoder decoder) {
147147
List<String> annotations = Linq.list(
148148
Linq.map(Utilities.getProperty(node, "annotations").elements(),
149149
JsonNode::asText));
150-
return new DBSPFunction(name, parameters, returnType, body, annotations);
150+
return new DBSPFunction(CalciteObject.EMPTY, name, parameters, returnType, body, annotations);
151151
}
152152
}

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/ir/statement/DBSPComparatorItem.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class DBSPComparatorItem extends DBSPItem {
1313
public final DBSPComparatorExpression expression;
1414

1515
public DBSPComparatorItem(DBSPComparatorExpression expression) {
16+
super(expression.getNode());
1617
this.expression = expression;
1718
}
1819

0 commit comments

Comments
 (0)