Skip to content

Commit e242baf

Browse files
authored
Initial support for DROP TEMPORARY FUNCTION (#3492)
This PR provides an initial support for ‘DROP TEMPORARY FUNCTION’ DDL statement. It does so by creating a new ConstantAction-based ProceduralPlan that does the simple remove key operation from the invokedRoutines in transaction-based SchemaTemplate. Note that it does not evaluate if other functions transitively depend on the function marked for deletion and hence, does not perform cascading delete or rejects the current delete. As a result, compiled dependant functions still succeeds. This could be solved by having some dependency graph in the schema template. This is out of the scope of the current PR. #3493 Also includes tests for the same. This PR also adapts TransactionBoundDatabase to provide drop temporary function operation to it as well.
1 parent e8c9e5e commit e242baf

File tree

15 files changed

+356
-11
lines changed

15 files changed

+356
-11
lines changed

fdb-relational-api/src/main/java/com/apple/foundationdb/relational/api/exceptions/ErrorCode.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ public enum ErrorCode {
120120
DATABASE_ALREADY_EXISTS("42F04"),
121121
SCHEMA_ALREADY_EXISTS("42F06"),
122122
TABLE_ALREADY_EXISTS("42F07"),
123-
FUNCTION_ALREADY_EXISTS("42F08"),
124123
INVALID_COLUMN_REFERENCE("42F10"), //no field of specified name in the result set
125124
INVALID_FUNCTION_DEFINITION("42F13"),
126125
INVALID_TABLE_DEFINITION("42F16"),

fdb-relational-core/src/main/antlr/RelationalParser.g4

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ ddlStatement
5858
: createStatement
5959
| dropStatement
6060
| createTempFunction
61+
| dropTempFunction
6162
;
6263

6364
transactionStatement
@@ -172,6 +173,10 @@ createTempFunction
172173
: CREATE (OR REPLACE)? TEMPORARY tempSqlInvokedFunction
173174
;
174175

176+
dropTempFunction
177+
: DROP TEMPORARY FUNCTION (IF EXISTS)? schemaQualifiedRoutineName=fullId
178+
;
179+
175180
createFunction
176181
: CREATE sqlInvokedFunction
177182
;

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/api/ddl/MetadataOperationsFactory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ public interface MetadataOperationsFactory {
5151
ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull String schemaName, @Nonnull Options options);
5252

5353
@Nonnull
54-
ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull SchemaTemplate template, boolean throwIfNotExist, @Nonnull RecordLayerInvokedRoutine invokedRoutine,
54+
ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull SchemaTemplate template, boolean throwIfExists, @Nonnull RecordLayerInvokedRoutine invokedRoutine,
5555
@Nonnull PreparedParams preparedParams);
56+
57+
@Nonnull
58+
ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists, @Nonnull String temporaryFunctionName);
5659
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/catalog/TransactionBoundDatabase.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.apple.foundationdb.relational.recordlayer.RecordStoreAndRecordContextTransaction;
3939
import com.apple.foundationdb.relational.recordlayer.ddl.AbstractMetadataOperationsFactory;
4040
import com.apple.foundationdb.relational.recordlayer.ddl.CreateTemporaryFunctionConstantAction;
41+
import com.apple.foundationdb.relational.recordlayer.ddl.DropTemporaryFunctionConstantAction;
4142
import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerInvokedRoutine;
4243
import com.apple.foundationdb.relational.recordlayer.query.PreparedParams;
4344
import com.apple.foundationdb.relational.recordlayer.query.cache.RelationalPlanCache;
@@ -67,16 +68,22 @@ public class TransactionBoundDatabase extends AbstractDatabase {
6768
@Nonnull
6869
final Options options;
6970

70-
private static final MetadataOperationsFactory metadataOperationsFactory = new AbstractMetadataOperationsFactory() {
71+
private static final MetadataOperationsFactory onlyTemporaryFunctionOperationsFactory = new AbstractMetadataOperationsFactory() {
7172
@Nonnull
7273
@Override
73-
public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, final boolean throwIfNotExists, @Nonnull final RecordLayerInvokedRoutine invokedRoutine, @Nonnull final PreparedParams preparedParams) {
74-
return new CreateTemporaryFunctionConstantAction(template, throwIfNotExists, invokedRoutine, preparedParams);
74+
public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, final boolean throwIfExists, @Nonnull final RecordLayerInvokedRoutine invokedRoutine, @Nonnull final PreparedParams preparedParams) {
75+
return new CreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine, preparedParams);
76+
}
77+
78+
@Nonnull
79+
@Override
80+
public ConstantAction getDropTemporaryFunctionConstantAction(final boolean throwIfNotExists, @Nonnull final String temporaryFunctionName) {
81+
return new DropTemporaryFunctionConstantAction(throwIfNotExists, temporaryFunctionName);
7582
}
7683
};
7784

7885
public TransactionBoundDatabase(URI uri, @Nonnull Options options, @Nullable RelationalPlanCache planCache) {
79-
super(metadataOperationsFactory, NoOpQueryFactory.INSTANCE, planCache);
86+
super(onlyTemporaryFunctionOperationsFactory, NoOpQueryFactory.INSTANCE, planCache);
8087
this.uri = uri;
8188
this.options = options;
8289
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/AbstractMetadataOperationsFactory.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,15 @@ public ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templa
7272

7373
@Nonnull
7474
@Override
75-
public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, boolean throwIfNotExists,
75+
public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, boolean throwIfExists,
7676
@Nonnull final RecordLayerInvokedRoutine invokedRoutine, @Nonnull final PreparedParams preparedParams) {
77-
return NoOpMetadataOperationsFactory.INSTANCE.getCreateTemporaryFunctionConstantAction(template, throwIfNotExists, invokedRoutine, preparedParams);
77+
return NoOpMetadataOperationsFactory.INSTANCE.getCreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine, preparedParams);
78+
}
79+
80+
@Nonnull
81+
@Override
82+
public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists,
83+
@Nonnull final String temporaryFunctionName) {
84+
return NoOpMetadataOperationsFactory.INSTANCE.getDropTemporaryFunctionConstantAction(throwIfNotExists, temporaryFunctionName);
7885
}
7986
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* DropTemporaryFunctionConstantAction.java
3+
*
4+
* This source file is part of the FoundationDB open source project
5+
*
6+
* Copyright 2015-2025 Apple Inc. and the FoundationDB project authors
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
package com.apple.foundationdb.relational.recordlayer.ddl;
22+
23+
import com.apple.foundationdb.relational.api.Transaction;
24+
import com.apple.foundationdb.relational.api.ddl.ConstantAction;
25+
import com.apple.foundationdb.relational.api.exceptions.ErrorCode;
26+
import com.apple.foundationdb.relational.api.exceptions.RelationalException;
27+
import com.apple.foundationdb.relational.recordlayer.metadata.RecordLayerSchemaTemplate;
28+
import com.apple.foundationdb.relational.util.Assert;
29+
30+
import javax.annotation.Nonnull;
31+
32+
public class DropTemporaryFunctionConstantAction implements ConstantAction {
33+
34+
private final boolean throwIfNotExists;
35+
36+
@Nonnull
37+
private final String temporaryFunctionName;
38+
39+
public DropTemporaryFunctionConstantAction(boolean throwIfNotExists,
40+
@Nonnull final String temporaryFunctionName) {
41+
this.throwIfNotExists = throwIfNotExists;
42+
this.temporaryFunctionName = temporaryFunctionName;
43+
}
44+
45+
@Override
46+
public void execute(final Transaction txn) throws RelationalException {
47+
final var transactionBoundSchemaTemplate = txn.getBoundSchemaTemplateMaybe();
48+
if (transactionBoundSchemaTemplate.isPresent()) {
49+
final var relationalLayerSchemaTemplate = Assert.castUnchecked(transactionBoundSchemaTemplate.orElseThrow(), RecordLayerSchemaTemplate.class);
50+
final var maybeInvokedRoutine = relationalLayerSchemaTemplate.getInvokedRoutines().stream().filter(r -> r.getName().equals(temporaryFunctionName)).findFirst();
51+
if (maybeInvokedRoutine.isPresent()) {
52+
Assert.thatUnchecked(maybeInvokedRoutine.orElseThrow().isTemporary(), ErrorCode.INVALID_FUNCTION_DEFINITION, "Attempt to DROP an non-temporary function: " + temporaryFunctionName);
53+
final var schemaTemplateWithoutTempFunction = relationalLayerSchemaTemplate.toBuilder().removeInvokedRoutine(temporaryFunctionName).build();
54+
txn.setBoundSchemaTemplate(schemaTemplateWithoutTempFunction);
55+
return;
56+
}
57+
}
58+
Assert.thatUnchecked(!throwIfNotExists, ErrorCode.UNDEFINED_FUNCTION, "Attempt to DROP an undefined temporary function: " + temporaryFunctionName);
59+
}
60+
}

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/NoOpMetadataOperationsFactory.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,19 @@ public ConstantAction getDropSchemaConstantAction(@Nonnull URI dbPath, @Nonnull
7272

7373
@Nonnull
7474
@Override
75-
public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, boolean throwIfNotExists,
75+
public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull final SchemaTemplate template, boolean throwIfExists,
7676
@Nonnull final RecordLayerInvokedRoutine invokedRoutine,
7777
@Nonnull final PreparedParams preparedParams) {
7878
return NoOpConstantAction.INSTANCE;
7979
}
8080

81+
@Nonnull
82+
@Override
83+
public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists,
84+
@Nonnull final String temporaryFunctionName) {
85+
return NoOpConstantAction.INSTANCE;
86+
}
87+
8188
@Nonnull
8289
@Override
8390
public ConstantAction getDropSchemaTemplateConstantAction(@Nonnull String templateId, boolean throwIfDoesNotExist, @Nonnull Options options) {

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/ddl/RecordLayerMetadataOperationsFactory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ public ConstantAction getCreateTemporaryFunctionConstantAction(@Nonnull SchemaTe
9999
return new CreateTemporaryFunctionConstantAction(template, throwIfExists, invokedRoutine, preparedParams);
100100
}
101101

102+
@Nonnull
103+
@Override
104+
public ConstantAction getDropTemporaryFunctionConstantAction(boolean throwIfNotExists,
105+
@Nonnull final String temporaryFunctionName) {
106+
return new DropTemporaryFunctionConstantAction(throwIfNotExists, temporaryFunctionName);
107+
}
108+
102109
public static class Builder {
103110
protected StoreCatalog storeCatalog;
104111
protected RecordLayerConfig rlConfig;

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/metadata/RecordLayerSchemaTemplate.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,15 @@ public Builder replaceInvokedRoutine(@Nonnull final RecordLayerInvokedRoutine in
476476
return this;
477477
}
478478

479+
public Builder removeInvokedRoutine(@Nonnull final String invokedRoutineName) {
480+
if (!invokedRoutines.containsKey(invokedRoutineName)) {
481+
Assert.thatUnchecked(invokedRoutines.get(invokedRoutineName).isTemporary(), ErrorCode.UNDEFINED_FUNCTION,
482+
"attempt to non-existent temporary invoked routine!");
483+
}
484+
invokedRoutines.remove(invokedRoutineName);
485+
return this;
486+
}
487+
479488
@Nonnull
480489
public Builder addInvokedRoutines(@Nonnull final Collection<RecordLayerInvokedRoutine> invokedRoutines) {
481490
invokedRoutines.forEach(this::addInvokedRoutine);

fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/query/visitors/BaseVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,11 @@ public ProceduralPlan visitCreateTempFunction(final RelationalParser.CreateTempF
417417
return ddlVisitor.visitCreateTempFunction(ctx);
418418
}
419419

420+
@Override
421+
public ProceduralPlan visitDropTempFunction(final RelationalParser.DropTempFunctionContext ctx) {
422+
return ddlVisitor.visitDropTempFunction(ctx);
423+
}
424+
420425
@Override
421426
public CompiledSqlFunction visitCreateFunction(final RelationalParser.CreateFunctionContext ctx) {
422427
return ddlVisitor.visitCreateFunction(ctx);

0 commit comments

Comments
 (0)