Skip to content

Commit 8e96d89

Browse files
committed
add UnaryFunctionColumnConstraint
1 parent e1b8a71 commit 8e96d89

File tree

6 files changed

+187
-49
lines changed

6 files changed

+187
-49
lines changed

src/antlr/Parser.g

+1-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ columnConstraints returns [ColumnConstraints.Raw constraints]
796796

797797
columnConstraint returns [ColumnConstraint columnConstraint]
798798
: funcName=ident '(' k=ident ')' op=relationType t=value { $columnConstraint = new FunctionColumnConstraint.Raw(funcName, k, op, t.getText()).prepare(); }
799-
| funcName=ident '(' k=ident ')' { $columnConstraint = new FunctionColumnConstraint.Raw(funcName, k).prepare(); }
799+
| funcName=ident '(' k=ident ')' { $columnConstraint = new UnaryFunctionColumnConstraint.Raw(funcName, k).prepare(); }
800800
| k=ident op=relationType t=value { $columnConstraint = new ScalarColumnConstraint.Raw(k, op, t.getText()).prepare(); }
801801
;
802802

src/java/org/apache/cassandra/cql3/constraints/ColumnConstraint.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ enum ConstraintType
4141
// Changing this enum would affect how that int is interpreted when deserializing.
4242
COMPOSED(ColumnConstraints.serializer),
4343
FUNCTION(FunctionColumnConstraint.serializer),
44-
SCALAR(ScalarColumnConstraint.serializer);
44+
SCALAR(ScalarColumnConstraint.serializer),
45+
UNARY_FUNCTION(UnaryFunctionColumnConstraint.serializer);
4546

4647
private final MetadataSerializer<?> serializer;
4748

src/java/org/apache/cassandra/cql3/constraints/ConstraintFunction.java

+8
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ public interface ConstraintFunction
4040
*/
4141
void evaluate(AbstractType<?> valueType, Operator relationType, String term, ByteBuffer columnValue) throws ConstraintViolationException;
4242

43+
/**
44+
* Used mostly for unary functions which do not expect any relation type nor term.
45+
*/
46+
default void evaluate(AbstractType<?> valueType, ByteBuffer columnValue) throws ConstraintViolationException
47+
{
48+
evaluate(valueType, null, null, columnValue);
49+
}
50+
4351
/**
4452
* Method that validates that a condition is valid. This method is called when the CQL constraint is created to determine
4553
* if the CQL statement is valid or needs to be rejected as invalid throwing a {@link InvalidConstraintDefinitionException}

src/java/org/apache/cassandra/cql3/constraints/FunctionColumnConstraint.java

+11-46
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ public Raw(ColumnIdentifier functionName, ColumnIdentifier columnName, Operator
5858
function = createConstraintFunction(functionName.toCQLString(), columnName);
5959
}
6060

61-
public Raw(ColumnIdentifier functionName, ColumnIdentifier columnName)
62-
{
63-
this(functionName, columnName, null, null);
64-
}
65-
6661
public FunctionColumnConstraint prepare()
6762
{
6863
return new FunctionColumnConstraint(function, columnName, relationType, term);
@@ -71,8 +66,7 @@ public FunctionColumnConstraint prepare()
7166

7267
private enum Functions
7368
{
74-
LENGTH(LengthConstraint::new),
75-
NOT_NULL(NotNullConstraint::new);
69+
LENGTH(LengthConstraint::new);
7670

7771
private final Function<ColumnIdentifier, ConstraintFunction> functionCreator;
7872

@@ -142,10 +136,6 @@ void validateArgs(ColumnMetadata columnMetadata)
142136
@Override
143137
public String toString()
144138
{
145-
// constraint without relation
146-
if (relationType == null)
147-
return function.getName() + "(" + columnName + ") ";
148-
149139
return function.getName() + "(" + columnName + ") " + relationType + " " + term;
150140
}
151141

@@ -156,17 +146,8 @@ public void serialize(FunctionColumnConstraint columnConstraint, DataOutputPlus
156146
{
157147
out.writeUTF(columnConstraint.function.getName());
158148
out.writeUTF(columnConstraint.columnName.toCQLString());
159-
160-
if (columnConstraint.relationType != null && columnConstraint.term != null)
161-
{
162-
out.writeBoolean(true);
163-
columnConstraint.relationType.writeTo(out);
164-
out.writeUTF(columnConstraint.term);
165-
}
166-
else
167-
{
168-
out.writeBoolean(false);
169-
}
149+
columnConstraint.relationType.writeTo(out);
150+
out.writeUTF(columnConstraint.term);
170151
}
171152

172153
@Override
@@ -184,18 +165,8 @@ public FunctionColumnConstraint deserialize(DataInputPlus in, Version version) t
184165
{
185166
throw new IOException(e);
186167
}
187-
188-
boolean hasRelation = in.readBoolean();
189-
190-
Operator relationType = null;
191-
String term = null;
192-
193-
if (hasRelation)
194-
{
195-
relationType = Operator.readFrom(in);
196-
term = in.readUTF();
197-
}
198-
168+
Operator relationType = Operator.readFrom(in);
169+
final String term = in.readUTF();
199170
return new FunctionColumnConstraint(function, columnName, relationType, term);
200171
}
201172

@@ -204,10 +175,8 @@ public long serializedSize(FunctionColumnConstraint columnConstraint, Version ve
204175
{
205176
return TypeSizes.sizeof(columnConstraint.function.getClass().getName())
206177
+ TypeSizes.sizeof(columnConstraint.columnName.toCQLString())
207-
+ (long) TypeSizes.BOOL_SIZE
208-
+ (columnConstraint.relationType != null && columnConstraint.term != null
209-
? (TypeSizes.sizeof(columnConstraint.term) + Operator.serializedSize())
210-
: 0);
178+
+ TypeSizes.sizeof(columnConstraint.term)
179+
+ Operator.serializedSize();
211180
}
212181
}
213182

@@ -222,13 +191,9 @@ public boolean equals(Object o)
222191

223192
FunctionColumnConstraint other = (FunctionColumnConstraint) o;
224193

225-
if (relationType != null && term != null)
226-
return function.equals(other.function)
227-
&& columnName.equals(other.columnName)
228-
&& relationType == other.relationType
229-
&& term.equals(other.term);
230-
else
231-
return function.equals(other.function)
232-
&& columnName.equals(other.columnName);
194+
return function.equals(other.function)
195+
&& columnName.equals(other.columnName)
196+
&& relationType == other.relationType
197+
&& term.equals(other.term);
233198
}
234199
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.cassandra.cql3.constraints;
20+
21+
import java.io.IOException;
22+
import java.nio.ByteBuffer;
23+
import java.util.function.Function;
24+
25+
import org.apache.cassandra.cql3.ColumnIdentifier;
26+
import org.apache.cassandra.cql3.CqlBuilder;
27+
import org.apache.cassandra.db.TypeSizes;
28+
import org.apache.cassandra.db.marshal.AbstractType;
29+
import org.apache.cassandra.io.util.DataInputPlus;
30+
import org.apache.cassandra.io.util.DataOutputPlus;
31+
import org.apache.cassandra.schema.ColumnMetadata;
32+
import org.apache.cassandra.tcm.serialization.MetadataSerializer;
33+
import org.apache.cassandra.tcm.serialization.Version;
34+
import org.apache.cassandra.utils.LocalizeString;
35+
36+
import static org.apache.cassandra.cql3.constraints.ColumnConstraint.ConstraintType.UNARY_FUNCTION;
37+
38+
public class UnaryFunctionColumnConstraint implements ColumnConstraint<UnaryFunctionColumnConstraint>
39+
{
40+
public static final Serializer serializer = new Serializer();
41+
42+
public final ConstraintFunction function;
43+
public final ColumnIdentifier columnName;
44+
45+
public final static class Raw
46+
{
47+
public final ConstraintFunction function;
48+
public final ColumnIdentifier columnName;
49+
50+
public Raw(ColumnIdentifier functionName, ColumnIdentifier columnName)
51+
{
52+
this.columnName = columnName;
53+
function = createConstraintFunction(functionName.toCQLString(), columnName);
54+
}
55+
56+
public UnaryFunctionColumnConstraint prepare()
57+
{
58+
return new UnaryFunctionColumnConstraint(function, columnName);
59+
}
60+
}
61+
62+
private enum Functions
63+
{
64+
NOT_NULL(NotNullConstraint::new);
65+
66+
private final Function<ColumnIdentifier, ConstraintFunction> functionCreator;
67+
68+
Functions(Function<ColumnIdentifier, ConstraintFunction> functionCreator)
69+
{
70+
this.functionCreator = functionCreator;
71+
}
72+
}
73+
74+
private static ConstraintFunction createConstraintFunction(String functionName, ColumnIdentifier columnName)
75+
{
76+
try
77+
{
78+
return Functions.valueOf(LocalizeString.toUpperCaseLocalized(functionName)).functionCreator.apply(columnName);
79+
}
80+
catch (IllegalArgumentException ex)
81+
{
82+
throw new InvalidConstraintDefinitionException("Unrecognized constraint function: " + functionName);
83+
}
84+
}
85+
86+
private UnaryFunctionColumnConstraint(ConstraintFunction function, ColumnIdentifier columnName)
87+
{
88+
this.function = function;
89+
this.columnName = columnName;
90+
}
91+
92+
@Override
93+
public MetadataSerializer<UnaryFunctionColumnConstraint> serializer()
94+
{
95+
return serializer;
96+
}
97+
98+
@Override
99+
public void appendCqlTo(CqlBuilder builder)
100+
{
101+
builder.append(toString());
102+
}
103+
104+
@Override
105+
public void evaluate(AbstractType<?> valueType, ByteBuffer columnValue) throws ConstraintViolationException
106+
{
107+
function.evaluate(valueType, columnValue);
108+
}
109+
110+
@Override
111+
public void validate(ColumnMetadata columnMetadata) throws InvalidConstraintDefinitionException
112+
{
113+
function.validate(columnMetadata);
114+
}
115+
116+
@Override
117+
public ConstraintType getConstraintType()
118+
{
119+
return UNARY_FUNCTION;
120+
}
121+
122+
@Override
123+
public String toString()
124+
{
125+
return function.getName() + '(' + columnName + ") ";
126+
}
127+
128+
public static class Serializer implements MetadataSerializer<UnaryFunctionColumnConstraint>
129+
{
130+
@Override
131+
public void serialize(UnaryFunctionColumnConstraint columnConstraint, DataOutputPlus out, Version version) throws IOException
132+
{
133+
out.writeUTF(columnConstraint.function.getName());
134+
out.writeUTF(columnConstraint.columnName.toCQLString());
135+
}
136+
137+
@Override
138+
public UnaryFunctionColumnConstraint deserialize(DataInputPlus in, Version version) throws IOException
139+
{
140+
String functionName = in.readUTF();
141+
ConstraintFunction function;
142+
String columnNameString = in.readUTF();
143+
ColumnIdentifier columnName = new ColumnIdentifier(columnNameString, true);
144+
try
145+
{
146+
function = createConstraintFunction(functionName, columnName);
147+
}
148+
catch (Exception e)
149+
{
150+
throw new IOException(e);
151+
}
152+
153+
return new UnaryFunctionColumnConstraint(function, columnName);
154+
}
155+
156+
@Override
157+
public long serializedSize(UnaryFunctionColumnConstraint columnConstraint, Version version)
158+
{
159+
return TypeSizes.sizeof(columnConstraint.function.getClass().getName())
160+
+ TypeSizes.sizeof(columnConstraint.columnName.toCQLString());
161+
}
162+
}
163+
}

test/unit/org/apache/cassandra/contraints/ColumnConstraintsTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@
2525
import static org.apache.cassandra.cql3.constraints.ColumnConstraint.ConstraintType.COMPOSED;
2626
import static org.apache.cassandra.cql3.constraints.ColumnConstraint.ConstraintType.FUNCTION;
2727
import static org.apache.cassandra.cql3.constraints.ColumnConstraint.ConstraintType.SCALAR;
28+
import static org.apache.cassandra.cql3.constraints.ColumnConstraint.ConstraintType.UNARY_FUNCTION;
2829
import static org.junit.Assert.assertEquals;
2930

3031
public class ColumnConstraintsTest
3132
{
32-
private static final ConstraintType[] EXPECTED_VALUES = { COMPOSED, FUNCTION, SCALAR };
33+
private static final ConstraintType[] EXPECTED_VALUES = { COMPOSED, FUNCTION, SCALAR, UNARY_FUNCTION };
3334

3435
@Test
3536
public void testEnumCodesAndNames()

0 commit comments

Comments
 (0)