This is an automated email from the ASF dual-hosted git repository. blerer pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push: new 5cf62c6 Add support for string concatenations through the + operator 5cf62c6 is described below commit 5cf62c6c02322505db9260d2aa9031386326fc75 Author: Manish Ghildiyal <manish.ghildi...@lunatech.be> AuthorDate: Sat Dec 18 18:26:31 2021 +0100 Add support for string concatenations through the + operator Patch by Manish Ghildiyal; review by Benjamin Lerer, Berenguer Blassi, Brandon Williams for CASSANDRA-17190 --- CHANGES.txt | 1 + NEWS.txt | 1 + src/java/org/apache/cassandra/cql3/Constants.java | 14 +++- .../cassandra/cql3/functions/OperationFcts.java | 92 ++++++++++++++++++---- .../apache/cassandra/db/marshal/StringType.java | 13 +++ .../cql3/functions/OperationFctsTest.java | 14 ++++ 6 files changed, 118 insertions(+), 17 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 2a313ab..51e39bf 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.1 + * Add support for string concatenations through the + operator (CASSANDRA-17190) * Limit the maximum hints size per host (CASSANDRA-17142) * Add a virtual table for exposing batch metrics (CASSANDRA-17225) * Flatten guardrails config (CASSANDRA-17353) diff --git a/NEWS.txt b/NEWS.txt index f5d76d5..26a1c8d 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -38,6 +38,7 @@ using the provided 'sstableupgrade' tool. New features ------------ + - Support for String concatenation has been added through the + operator. - New configuration max_hints_size_per_host to limit the size of local hints files per host in megabytes. Setting to non-positive value disables the limit, which is the default behavior. Setting to a positive value to ensure the total size of the hints files per host does not exceed the limit. diff --git a/src/java/org/apache/cassandra/cql3/Constants.java b/src/java/org/apache/cassandra/cql3/Constants.java index 3457e33..e8989ad 100644 --- a/src/java/org/apache/cassandra/cql3/Constants.java +++ b/src/java/org/apache/cassandra/cql3/Constants.java @@ -20,6 +20,7 @@ package org.apache.cassandra.cql3; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.nio.charset.Charset; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +45,18 @@ public abstract class Constants public enum Type { - STRING, + STRING + { + public AbstractType<?> getPreferedTypeFor(String text) + { + if(Charset.forName("US-ASCII").newEncoder().canEncode(text)) + { + return AsciiType.instance; + } + + return UTF8Type.instance; + } + }, INTEGER { public AbstractType<?> getPreferedTypeFor(String text) diff --git a/src/java/org/apache/cassandra/cql3/functions/OperationFcts.java b/src/java/org/apache/cassandra/cql3/functions/OperationFcts.java index 4994660..b00ced7 100644 --- a/src/java/org/apache/cassandra/cql3/functions/OperationFcts.java +++ b/src/java/org/apache/cassandra/cql3/functions/OperationFcts.java @@ -53,14 +53,24 @@ public final class OperationFcts { return type.addDuration(temporal, duration); } + + @Override + protected ByteBuffer excuteOnStrings(StringType resultType, + StringType leftType, + ByteBuffer left, + StringType rightType, + ByteBuffer right) + { + return resultType.concat(leftType, left, rightType, right); + } }, SUBSTRACTION('-', "_substract") { protected ByteBuffer executeOnNumerics(NumberType<?> resultType, - NumberType<?> leftType, - ByteBuffer left, - NumberType<?> rightType, - ByteBuffer right) + NumberType<?> leftType, + ByteBuffer left, + NumberType<?> rightType, + ByteBuffer right) { return resultType.substract(leftType, left, rightType, right); } @@ -76,10 +86,10 @@ public final class OperationFcts MULTIPLICATION('*', "_multiply") { protected ByteBuffer executeOnNumerics(NumberType<?> resultType, - NumberType<?> leftType, - ByteBuffer left, - NumberType<?> rightType, - ByteBuffer right) + NumberType<?> leftType, + ByteBuffer left, + NumberType<?> rightType, + ByteBuffer right) { return resultType.multiply(leftType, left, rightType, right); } @@ -87,10 +97,10 @@ public final class OperationFcts DIVISION('/', "_divide") { protected ByteBuffer executeOnNumerics(NumberType<?> resultType, - NumberType<?> leftType, - ByteBuffer left, - NumberType<?> rightType, - ByteBuffer right) + NumberType<?> leftType, + ByteBuffer left, + NumberType<?> rightType, + ByteBuffer right) { return resultType.divide(leftType, left, rightType, right); } @@ -98,10 +108,10 @@ public final class OperationFcts MODULO('%', "_modulo") { protected ByteBuffer executeOnNumerics(NumberType<?> resultType, - NumberType<?> leftType, - ByteBuffer left, - NumberType<?> rightType, - ByteBuffer right) + NumberType<?> leftType, + ByteBuffer left, + NumberType<?> rightType, + ByteBuffer right) { return resultType.mod(leftType, left, rightType, right); } @@ -155,6 +165,25 @@ public final class OperationFcts } /** + * Executes the operation between the specified string operand. + * + * @param resultType the result type of the operation + * @param leftType the type of the left operand + * @param left the left operand + * @param rightType the type of the right operand + * @param right the right operand + * @return the operation result + */ + protected ByteBuffer excuteOnStrings(StringType resultType, + StringType leftType, + ByteBuffer left, + StringType rightType, + ByteBuffer right) + { + throw new UnsupportedOperationException(); + } + + /** * Returns the {@code OPERATOR} associated to the specified function. * @param functionName the function name * @return the {@code OPERATOR} associated to the specified function @@ -221,9 +250,19 @@ public final class OperationFcts functions.add(new TemporalOperationFunction(SimpleDateType.instance, operation)); } + addStringConcatenations(functions); + return functions; } + private static void addStringConcatenations(List<Function> functions) + { + functions.add(new StringOperationFunction(UTF8Type.instance, UTF8Type.instance, OPERATION.ADDITION, UTF8Type.instance)); + functions.add(new StringOperationFunction(AsciiType.instance, AsciiType.instance, OPERATION.ADDITION, AsciiType.instance)); + functions.add(new StringOperationFunction(UTF8Type.instance, AsciiType.instance, OPERATION.ADDITION, UTF8Type.instance)); + functions.add(new StringOperationFunction(UTF8Type.instance, UTF8Type.instance, OPERATION.ADDITION, AsciiType.instance)); + } + /** * Checks if the function with the specified name is an operation. * @@ -415,6 +454,27 @@ public final class OperationFcts } } + private static class StringOperationFunction extends OperationFunction + { + public StringOperationFunction(StringType returnType, + StringType left, + OPERATION operation, + StringType right) + { + super(returnType, left, operation, right); + } + + @Override + protected ByteBuffer doExecute(ByteBuffer left, OPERATION operation, ByteBuffer right) + { + StringType leftType = (StringType) argTypes().get(0); + StringType rightType = (StringType) argTypes().get(1); + StringType resultType = (StringType) returnType(); + + return operation.excuteOnStrings(resultType, leftType, left, rightType, right); + } + } + /** * Function that execute operations on temporals (timestamp, date, ...). */ diff --git a/src/java/org/apache/cassandra/db/marshal/StringType.java b/src/java/org/apache/cassandra/db/marshal/StringType.java index f9ce444..29aff58 100644 --- a/src/java/org/apache/cassandra/db/marshal/StringType.java +++ b/src/java/org/apache/cassandra/db/marshal/StringType.java @@ -18,10 +18,23 @@ package org.apache.cassandra.db.marshal; +import java.nio.ByteBuffer; + public abstract class StringType extends AbstractType<String> { protected StringType(ComparisonType comparisonType) { super(comparisonType); } + + public ByteBuffer concat(StringType leftType, + ByteBuffer left, + StringType rightType, + ByteBuffer right) + { + String leftS = leftType.compose(left); + String rightS = rightType.compose(right); + + return decompose(leftS + rightS); + } } diff --git a/test/unit/org/apache/cassandra/cql3/functions/OperationFctsTest.java b/test/unit/org/apache/cassandra/cql3/functions/OperationFctsTest.java index 053283d..58c2c29 100644 --- a/test/unit/org/apache/cassandra/cql3/functions/OperationFctsTest.java +++ b/test/unit/org/apache/cassandra/cql3/functions/OperationFctsTest.java @@ -33,6 +33,20 @@ import org.apache.cassandra.transport.ProtocolVersion; public class OperationFctsTest extends CQLTester { + + @Test + public void testStringConcatenation() throws Throwable + { + createTable("CREATE TABLE %s (a text, b ascii, c text, PRIMARY KEY(a, b, c))"); + execute("INSERT INTO %S (a, b, c) VALUES ('जॉन', 'Doe', 'जॉन Doe')"); + + assertColumnNames(execute("SELECT a + a, a + b, b + a, b + b FROM %s WHERE a = 'जॉन' AND b = 'Doe' AND c = 'जॉन Doe'"), + "a + a", "a + b", "b + a", "b + b"); + + assertRows(execute("SELECT a + ' ' + a, a + ' ' + b, b + ' ' + a, b + ' ' + b FROM %s WHERE a = 'जॉन' AND b = 'Doe' AND c = 'जॉन Doe'"), + row("जॉन जॉन", "जॉन Doe", "Doe जॉन", "Doe Doe")); + } + @Test public void testSingleOperations() throws Throwable { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org