macroguo-ghy commented on code in PR #3459: URL: https://github.com/apache/calcite/pull/3459#discussion_r1349635823
########## site/_docs/reference.md: ########## @@ -2769,6 +2769,7 @@ BigQuery's type system uses confusingly different names for types and functions: | b | TO_HEX(binary) | Converts *binary* into a hexadecimal varchar | b | FROM_HEX(varchar) | Converts a hexadecimal-encoded *varchar* into bytes | b o | LTRIM(string) | Returns *string* with all blanks removed from the start +| s | MAP(key, value [, key, value]*) | Returns a map with the given key/value pairs Review Comment: Empty map is a legal functon. Please add `MAP()` to the documentation. ########## core/src/main/codegen/templates/Parser.jj: ########## @@ -4886,14 +4886,21 @@ SqlNode MapConstructor() : { <MAP> { s = span(); } ( - LOOKAHEAD(1) - <LPAREN> - // by sub query "MAP (SELECT empno, deptno FROM emp)" - e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY) - <RPAREN> + ( + // empty map function call: "map()" + LOOKAHEAD(2) + <LPAREN> <RPAREN> { args = SqlNodeList.EMPTY; } + | + args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_ALL) + ) { - return SqlStdOperatorTable.MAP_QUERY.createCall( - s.end(this), e); + if (args.size() == 1 && args.get(0).isA(SqlKind.QUERY)) { + // MAP query constructor e.g. "MAP (SELECT empno, deptno FROM emps)" + return SqlStdOperatorTable.MAP_QUERY.createCall(s.end(this), args.get(0)); + } else { + // MAP function e.g. "MAP(1, 2)" equivalent to standard "MAP[1, 2]" + return SqlLibraryOperators.MAP.createCall(s.end(this), args.getList()); Review Comment: I think we can check if the size of args is an even number. ########## core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java: ########## @@ -1077,6 +1079,38 @@ private static RelDataType arrayReturnType(SqlOperatorBinding opBinding) { SqlLibraryOperators::arrayReturnType, OperandTypes.SAME_VARIADIC); + private static RelDataType mapReturnType(SqlOperatorBinding opBinding) { + Pair<@Nullable RelDataType, @Nullable RelDataType> type = + getComponentTypes( + opBinding.getTypeFactory(), opBinding.collectOperandTypes()); + return SqlTypeUtil.createMapType( + opBinding.getTypeFactory(), + requireNonNull(type.left, "inferred key type"), + requireNonNull(type.right, "inferred value type"), + false); + } + + private static Pair<@Nullable RelDataType, @Nullable RelDataType> getComponentTypes( + RelDataTypeFactory typeFactory, + List<RelDataType> argTypes) { + // special case, allows empty map + if (argTypes.size() == 0) { + return Pair.of(typeFactory.createUnknownType(), typeFactory.createUnknownType()); Review Comment: There is a subtle difference between `unknown` and `any`, can you please explain why `unknown` is used? ########## testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java: ########## @@ -6604,11 +6605,44 @@ private static void checkIf(SqlOperatorFixture f) { // test operands not in same type family. f.checkFails("^map_concat(map[1, null], array[1])^", "Parameters must be of the same type", false); + + // 2. check with map function, map(k, v ...) Review Comment: Can you please add some tests with `map()`, like `map_concat(map('foo', 1), map())`, `map_keys(map())` or `cast(map() as MAP<INTEGER, INTEGER>)`. Because the type of `map()` is `MAP<UNKNOWN, UNKNOWN>`, I am not sure if unknown component type will cause an error. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@calcite.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org