Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion babel/src/main/codegen/config.fmpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ data: {
"ISOYEAR"
"ISOLATION"
"JAVA"
"JSON"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to remove this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misoperation during merge.

"K"
"KEY"
"KEY_MEMBER"
Expand Down
1 change: 1 addition & 0 deletions core/src/main/codegen/templates/Parser.jj
Original file line number Diff line number Diff line change
Expand Up @@ -5137,6 +5137,7 @@ SqlCall JsonValueFunctionCall() :
}
}


List<SqlNode> JsonQueryEmptyOrErrorBehavior() :
{
final List<SqlNode> list = new ArrayList<SqlNode>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_LENGTH;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_PRETTY;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_REMOVE;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_STORAGE_SIZE;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_TYPE;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.REPEAT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.REVERSE;
Expand Down Expand Up @@ -474,6 +475,7 @@ public Expression implement(RexToLixTranslator translator,
defineMethod(JSON_PRETTY, BuiltInMethod.JSON_PRETTY.method, NullPolicy.ARG0);
defineMethod(JSON_LENGTH, BuiltInMethod.JSON_LENGTH.method, NullPolicy.ARG0);
defineMethod(JSON_REMOVE, BuiltInMethod.JSON_REMOVE.method, NullPolicy.ARG0);
defineMethod(JSON_STORAGE_SIZE, BuiltInMethod.JSON_STORAGE_SIZE.method, NullPolicy.ARG0);
defineMethod(JSON_OBJECT, BuiltInMethod.JSON_OBJECT.method, NullPolicy.NONE);
defineMethod(JSON_ARRAY, BuiltInMethod.JSON_ARRAY.method, NullPolicy.NONE);
aggMap.put(JSON_OBJECTAGG.with(SqlJsonConstructorNullClause.ABSENT_ON_NULL),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,9 @@ ExInst<CalciteException> invalidTypesForComparison(String clazzName0, String op,

@BaseMessage("Invalid input for JSON_REMOVE: document: ''{0}'', jsonpath expressions: ''{1}''")
ExInst<CalciteException> invalidInputForJsonRemove(String value, String pathSpecs);

@BaseMessage("Not a valid input for JSON_STORAGE_SIZE: ''{0}''")
ExInst<CalciteException> invalidInputForJsonStorageSize(String value);
}

// End CalciteResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,15 @@ public static String jsonRemove(JsonValueContext input, String... pathSpecs) {
}
}

public static Integer jsonStorageSize(String input) {
try {
return input == null ? null : JSON_PATH_JSON_PROVIDER.getObjectMapper()
.writeValueAsBytes(dejsonize(input)).length;
} catch (Exception e) {
throw RESOURCE.invalidInputForJsonStorageSize(input).ex();
}
}

public static boolean isJsonValue(String input) {
try {
dejsonize(input);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.sql.fun;

import org.apache.calcite.sql.SqlFunction;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.type.SqlTypeTransforms;

/**
* The <code>JSON_STORAGE_SIZE</code> function.
*/
public class SqlJsonStorageSizeFunction extends SqlFunction {

public SqlJsonStorageSizeFunction() {
super("JSON_STORAGE_SIZE",
SqlKind.OTHER_FUNCTION,
ReturnTypes.cascade(ReturnTypes.INTEGER_NULLABLE,
SqlTypeTransforms.FORCE_NULLABLE),
null,
OperandTypes.ANY,
SqlFunctionCategory.SYSTEM);
}
}

// End SqlJsonStorageSizeFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ private SqlLibraryOperators() {
@LibraryOperator(libraries = {MYSQL})
public static final SqlFunction JSON_REMOVE = new SqlJsonRemoveFunction();

@LibraryOperator(libraries = {MYSQL})
public static final SqlFunction JSON_STORAGE_SIZE = new SqlJsonStorageSizeFunction();

@LibraryOperator(libraries = {MYSQL, POSTGRESQL})
public static final SqlFunction REPEAT =
new SqlFunction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,9 @@ public boolean argumentMustBeScalar(int ordinal) {
@Deprecated // to be removed before 2.0
public static final SqlFunction JSON_REMOVE = SqlLibraryOperators.JSON_REMOVE;

@Deprecated // to be removed before 2.0
public static final SqlFunction JSON_STORAGE_SIZE = SqlLibraryOperators.JSON_STORAGE_SIZE;

public static final SqlJsonArrayAggAggFunction JSON_ARRAYAGG =
new SqlJsonArrayAggAggFunction(SqlKind.JSON_ARRAYAGG,
SqlJsonConstructorNullClause.ABSENT_ON_NULL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ public enum BuiltInMethod {
JSON_PRETTY(JsonFunctions.class, "jsonPretty", String.class),
JSON_LENGTH(JsonFunctions.class, "jsonLength", String.class),
JSON_REMOVE(JsonFunctions.class, "jsonRemove", String.class),
JSON_STORAGE_SIZE(JsonFunctions.class, "jsonStorageSize", String.class),
JSON_OBJECTAGG_ADD(JsonFunctions.class, "jsonObjectAggAdd", Map.class,
String.class, Object.class, SqlJsonConstructorNullClause.class),
JSON_ARRAY(JsonFunctions.class, "jsonArray",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,4 +288,5 @@ ExceptionWhileSerializingToJson=Cannot serialize object to JSON: ''{0}''
InvalidInputForJsonLength=Not a valid input for JSON_LENGTH: ''{0}''
InvalidInputForJsonKeys=Not a valid input for JSON_KEYS: ''{0}''
InvalidInputForJsonRemove=Invalid input for JSON_REMOVE: document: ''{0}'', jsonpath expressions: ''{1}''
InvalidInputForJsonStorageSize=Not a valid input for JSON_STORAGE_SIZE: ''{0}''
# End CalciteResource.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3291,12 +3291,19 @@ private void checkLiteral2(String expression, String expected) {

@Test public void testNumericFloorInSpark() {
final String query = "select floor(\"salary\") "
+ "from \"employee\"";
+ "from \"employee\"";
final String expected = "SELECT FLOOR(salary)\n"
+ "FROM foodmart.employee";
+ "FROM foodmart.employee";
sql(query).withSpark().ok(expected);
}

@Test public void testJsonStorageSize() {
String query = "select json_storage_size(\"product_name\") from \"product\"";
final String expected = "SELECT JSON_STORAGE_SIZE(\"product_name\")\n"
+ "FROM \"foodmart\".\"product\"";
sql(query).ok(expected);
}

@Test public void testJsonType() {
String query = "select json_type(\"product_name\") from \"product\"";
final String expected = "SELECT "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8676,6 +8676,13 @@ public void subTestIntervalSecondFailsValidation() {
"JSON_PRETTY(NULL)");
}

@Test public void testJsonStorageSize() {
checkExp("json_storage_size('foo')",
"JSON_STORAGE_SIZE('foo')");
checkExp("json_storage_size(null)",
"JSON_STORAGE_SIZE(NULL)");
}

@Test public void testJsonArrayAgg1() {
checkExp("json_arrayagg(\"column\")",
"JSON_ARRAYAGG(`column` ABSENT ON NULL)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,25 @@ private void checkNullOperand(SqlTester tester, String op) {
tester.checkNull("json_pretty(cast(null as varchar))");
}

@Test public void testJsonStorageSize() {
tester.checkString("json_storage_size('[100, \"sakila\", [1, 3, 5], 425.05]')",
"29", "INTEGER");
tester.checkString("json_storage_size('{\"a\": 1000,\"b\": \"aa\", \"c\": \"[1, 3, 5]\"}')",
"35", "INTEGER");
tester.checkString("json_storage_size('{\"a\": 1000, \"b\": \"wxyz\", \"c\": \"[1, 3]\"}')",
"34", "INTEGER");
tester.checkString("json_storage_size('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]')",
"36", "INTEGER");
tester.checkString("json_storage_size('12')",
"2", "INTEGER");
tester.checkString("json_storage_size('null')",
"4", "INTEGER");
tester.checkString("json_storage_size(cast(null as varchar(1)))",
null, "INTEGER");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this one? 'null' is a string, why does it return null? Is there case for It returns NULL if the argument is NULL.?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well,Thanks for reminding me. I adjusted this mistake.

tester.checkFails("json_storage_size('{]')",
"(?s).*Not a valid input.*", true);
}

@Test public void testJsonType() {
tester.setFor(SqlLibraryOperators.JSON_TYPE);
tester.checkString("json_type('\"1\"')",
Expand Down
18 changes: 15 additions & 3 deletions core/src/test/java/org/apache/calcite/test/JdbcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6893,10 +6893,22 @@ public void testJsonPretty() {

@Test public void testJsonRemove() {
CalciteAssert.that()
.query("SELECT JSON_REMOVE(v, '$[1]') AS c1\n"
+ "FROM (VALUES ('[\"a\", [\"b\", \"c\"], \"d\"]')) AS t(v)\n"
.query("SELECT JSON_REMOVE(v, '$[1]') AS c1\n"
+ "FROM (VALUES ('[\"a\", [\"b\", \"c\"], \"d\"]')) AS t(v)\n"
+ "limit 10")
.returns("C1=[\"a\",\"d\"]\n");
}

@Test
public void testJsonStorageSize() {
CalciteAssert.that()
.query("SELECT\n"
+ "JSON_STORAGE_SIZE('[100, \"sakila\", [1, 3, 5], 425.05]') AS A,\n"
+ "JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"a\", \"c\": \"[1, 3, 5, 7]\"}') AS B,\n"
+ "JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"xyz\", \"c\": \"[1, 3, 5, 7]\"}') AS C,\n"
+ "JSON_STORAGE_SIZE('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]') AS D\n"
+ "limit 10")
.returns("C1=[\"a\",\"d\"]\n");
.returns("A=29; B=35; C=37; D=36\n");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,17 @@ public void testJsonRemove() {
is("{}"));
}

public void testJsonStorageSize() {
assertJsonStorageSize("[100, \"sakila\", [1, 3, 5], 425.05]", is(29));
assertJsonStorageSize("null", is(4));
assertJsonStorageSize(null, nullValue());

String input = null;
CalciteException expected = new CalciteException(
"Not a valid input for JSON_STORAGE_SIZE: '" + input + "'", null);
assertJsonStorageSizeFailed(input, errorMatches(expected));
}

@Test
public void testJsonObjectAggAdd() {
Map<String, Object> map = new HashMap<>();
Expand Down Expand Up @@ -751,8 +762,22 @@ private void assertJsonKeysFailed(JsonFunctions.JsonValueContext input,
private void assertJsonRemove(JsonFunctions.JsonValueContext input, String[] pathSpecs,
Matcher<? super String> matcher) {
assertThat(invocationDesc(BuiltInMethod.JSON_REMOVE.getMethodName(), input, pathSpecs),
JsonFunctions.jsonRemove(input, pathSpecs),
matcher);
JsonFunctions.jsonRemove(input, pathSpecs),
matcher);
}

private void assertJsonStorageSize(String input,
Matcher<? super Integer> matcher) {
assertThat(invocationDesc(BuiltInMethod.JSON_STORAGE_SIZE.getMethodName(), input),
JsonFunctions.jsonStorageSize(input),
matcher);
}

private void assertJsonStorageSizeFailed(String input,
Matcher<? super Throwable> matcher) {
assertFailed(invocationDesc(BuiltInMethod.JSON_STORAGE_SIZE.getMethodName(), input),
() -> JsonFunctions.jsonStorageSize(input),
matcher);
}

private void assertDejsonize(String input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11011,6 +11011,12 @@ private void checkCustomColumnResolving(String table) {
"(.*)JSON_VALUE_EXPRESSION(.*)");
}

@Test public void testJsonStorageSize() {
check("select json_storage_size(ename) from emp");
checkExp("json_storage_size('{\"foo\":\"bar\"}')");
checkExpType("json_storage_size('{\"foo\":\"bar\"}')", "INTEGER");
}

@Test public void testJsonType() {
check("select json_type(ename) from emp");
checkExp("json_type('{\"foo\":\"bar\"}')");
Expand Down
24 changes: 24 additions & 0 deletions site/_docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2099,6 +2099,8 @@ semantics.
| m | JSON_KEYS(jsonValue [, path ]) | Returns a string indicating the keys of a JSON *jsonValue*
| m | JSON_REMOVE(jsonValue, path[, path]) | Removes data from *jsonValue* using a series of *path* expressions and returns the result
| m | REVERSE(string) | Returns the reverse order of *string*
| m | JSON_STORAGE_SIZE(jsonValue) | Returns an integer value indicating the size of a *jsonValue*
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"size" is too simple to describe the return. You can just use the words that MySQL already used, or make it anyway more detailed.

| m | JSON_STORAGE_SIZE(jsonValue) | Returns the number of bytes used to store the binary representation of a *jsonValue*
| o | DECODE(value, value1, result1 [, valueN, resultN ]* [, default ]) | Compares *value* to each *valueN* value one by one; if *value* is equal to a *valueN*, returns the corresponding *resultN*, else returns *default*, or NULL if *default* is not specified
| o | NVL(value1, value2) | Returns *value1* if *value1* is not null, otherwise *value2*
| o | LTRIM(string) | Returns *string* with all blanks removed from the start
Expand All @@ -2112,6 +2114,7 @@ semantics.
| m p | REPEAT(string, integer) | Returns a string of *integer* times *string*; Returns an empty string if *integer* is less than 1
| m | SPACE(integer) | Returns a string of *integer* spaces; Returns an empty string if *integer* is less than 1


Note:

* `JSON_TYPE` / `JSON_DEPTH` / `JSON_PRETTY` return null if the argument is null
Expand Down Expand Up @@ -2231,6 +2234,27 @@ LIMIT 10;
| ---------- |
| ["a", "d"] |


##### JSON_STORAGE_SIZE example

SQL

```SQL
SELECT
JSON_STORAGE_SIZE('[100, \"sakila\", [1, 3, 5], 425.05]') AS c1,
JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"a\", \"c\": \"[1, 3, 5, 7]\"}') AS c2,
JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"xyz\", \"c\": \"[1, 3, 5, 7]\"}') AS c3,
JSON_STORAGE_SIZE('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]') AS c4
limit 10;
```

Result

| c1 | c2 | c3 | c4 |
| -- | ---| ---| -- |
| 29 | 35 | 37 | 36 |


#### DECODE example

SQL
Expand Down