All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.table.codegen.calls.BinaryStringCallGen.scala Maven / Gradle / Ivy

The newest version!
/*
 * 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.flink.table.codegen.calls

import org.apache.calcite.runtime.SqlFunctions
import org.apache.calcite.sql.SqlOperator
import org.apache.calcite.sql.fun.SqlStdOperatorTable
import org.apache.calcite.sql.fun.SqlStdOperatorTable._
import org.apache.calcite.sql.fun.SqlTrimFunction.Flag.{BOTH, LEADING, TRAILING}
import org.apache.flink.table.api.types.{DataTypes, InternalType, MapType}
import org.apache.flink.table.codegen.CodeGenUtils._
import org.apache.flink.table.codegen.CodeGeneratorContext.BINARY_STRING
import org.apache.flink.table.codegen.calls.CallGenerator.{
  generateCallIfArgsNotNull, generateCallIfArgsNullable, generateReturnStringCallIfArgsNotNull}
import org.apache.flink.table.codegen.calls.ScalarOperators.generateNot
import org.apache.flink.table.codegen.{CodeGeneratorContext, GeneratedExpression}
import org.apache.flink.table.dataformat.BinaryMap
import org.apache.flink.table.functions.sql.ScalarSqlFunctions
import org.apache.flink.table.runtime.conversion.DataStructureConverters.genToInternal
import org.apache.flink.table.runtime.functions.{BuildInScalarFunctions, ScalarFunctions}

/**
  * Code generator for call with string parameters or return value.
  * 1.Some specific optimization of BinaryString.
  * 2.Deal with conversions between Java String and internal String.
  *
  * 

TODO Need to rewrite most of the methods here, calculated directly on the BinaryString * instead of convert BinaryString to String. */ object BinaryStringCallGen { def generateCallExpression( ctx: CodeGeneratorContext, operator: SqlOperator, operands: Seq[GeneratedExpression], returnType: InternalType): Option[GeneratedExpression] = { val generator = operator match { case SqlStdOperatorTable.LIKE => new LikeCallGen().generate(ctx, operands, DataTypes.BOOLEAN, nullCheck = true) case SqlStdOperatorTable.NOT_LIKE => generateNot(ctx, nullCheck = true, new LikeCallGen().generate(ctx, operands, DataTypes.BOOLEAN, nullCheck = true)) case ScalarSqlFunctions.SUBSTRING | ScalarSqlFunctions.SUBSTR => generateSubString(ctx, operands) case ScalarSqlFunctions.LEFT => generateLeft(ctx, operands.head, operands(1)) case ScalarSqlFunctions.RIGHT => generateRight(ctx, operands.head, operands(1)) case CHAR_LENGTH | CHARACTER_LENGTH | ScalarSqlFunctions.LENGTH => generateCharLength(ctx, operands) case SIMILAR_TO => generateSimilarTo(ctx, operands) case NOT_SIMILAR_TO => generateNot(ctx, nullCheck = true, generateSimilarTo(ctx, operands)) case ScalarSqlFunctions.REGEXP_EXTRACT => generateRegexpExtract(ctx, operands) case ScalarSqlFunctions.REGEXP_REPLACE => generateRegexpReplace(ctx, operands) case ScalarSqlFunctions.IS_DECIMAL => generateIsDecimal(ctx, operands) case ScalarSqlFunctions.IS_DIGIT => generateIsDigit(ctx, operands) case ScalarSqlFunctions.IS_ALPHA => generateIsAlpha(ctx, operands) case UPPER => generateUpper(ctx, operands) case LOWER => generateLower(ctx, operands) case INITCAP => generateInitcap(ctx, operands) case POSITION => generatePosition(ctx, operands) case ScalarSqlFunctions.LOCATE => generateLocate(ctx, operands) case OVERLAY => generateOverlay(ctx, operands) case ScalarSqlFunctions.LPAD => generateLpad(ctx, operands) case ScalarSqlFunctions.RPAD => generateRpad(ctx, operands) case ScalarSqlFunctions.REPEAT => generateRepeat(ctx, operands) case ScalarSqlFunctions.REVERSE => generateReverse(ctx, operands) case ScalarSqlFunctions.REPLACE => generateReplace(ctx, operands) case ScalarSqlFunctions.SPLIT_INDEX => generateSplitIndex(ctx, operands) case ScalarSqlFunctions.KEYVALUE => generateKeyValue(ctx, operands) case ScalarSqlFunctions.HASH_CODE if operands.head.resultType == DataTypes.STRING => generateHashCode(ctx, operands) case ScalarSqlFunctions.MD5 => generateMd5(ctx, operands) case ScalarSqlFunctions.SHA1 => generateSha1(ctx, operands) case ScalarSqlFunctions.SHA224 => generateSha224(ctx, operands) case ScalarSqlFunctions.SHA256 => generateSha256(ctx, operands) case ScalarSqlFunctions.SHA384 => generateSha384(ctx, operands) case ScalarSqlFunctions.SHA512 => generateSha512(ctx, operands) case ScalarSqlFunctions.SHA2 => generateSha2(ctx, operands) case ScalarSqlFunctions.PARSE_URL => generateParserUrl(ctx, operands) case ScalarSqlFunctions.FROM_BASE64 => generateFromBase64(ctx, operands) case ScalarSqlFunctions.TO_BASE64 => generateToBase64(ctx, operands) case ScalarSqlFunctions.CHR => generateChr(ctx, operands) case ScalarSqlFunctions.REGEXP => generateRegExp(ctx, operands) case ScalarSqlFunctions.JSON_VALUE => generateJsonValue(ctx, operands) case ScalarSqlFunctions.BIN => generateBin(ctx, operands) case ScalarSqlFunctions.CONCAT => operands.foreach(requireString(_, operator.getName)) generateConcat(ctx, nullCheck = true, operands) case ScalarSqlFunctions.CONCAT_WS => operands.foreach(requireString(_, operator.getName)) generateConcatWs(ctx, operands) case ScalarSqlFunctions.STR_TO_MAP => generateStrToMap(ctx, operands) case TRIM => generateTrim(ctx, operands) case ScalarSqlFunctions.LTRIM => generateTrimLeft(ctx, operands) case ScalarSqlFunctions.RTRIM => generateTrimRight(ctx, operands) case CONCAT => val left = operands.head val right = operands(1) requireString(left, operator.getName) generateArithmeticConcat(ctx, left, right) case ScalarSqlFunctions.UUID => generateUuid(ctx, operands) case ScalarSqlFunctions.ASCII => generateAscii(ctx, operands.head) case ScalarSqlFunctions.ENCODE => generateEncode(ctx, operands.head, operands(1)) case ScalarSqlFunctions.DECODE => generateDecode(ctx, operands.head, operands(1)) case ScalarSqlFunctions.INSTR => generateInstr(ctx, operands) case _ => null } Option(generator) } private def toStringTerms(terms: Seq[String], operands: Seq[GeneratedExpression]) = { terms.zipWithIndex.map { case (term, index) => if (operands(index).resultType == DataTypes.STRING) { s"$term.toString()" } else { term } }.mkString(",") } private def safeToStringTerms(terms: Seq[String], operands: Seq[GeneratedExpression]) = { terms.zipWithIndex.map { case (term, index) => if (operands(index).resultType == DataTypes.STRING) { s"$BINARY_STRING.safeToString($term)" } else { term } }.mkString(",") } def generateConcat( ctx: CodeGeneratorContext, nullCheck: Boolean, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNullable(ctx, nullCheck, DataTypes.STRING, operands) { terms => s"$BINARY_STRING.concat(${terms.mkString(", ")})" } } def generateConcatWs( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"$BINARY_STRING.concatWs(${terms.mkString(", ")})" } } /** * Optimization: use BinaryString equals instead of compare. */ def generateStringEquals( ctx: CodeGeneratorContext, left: GeneratedExpression, right: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.BOOLEAN, Seq(left, right)) { terms => s"(${terms.head}.equals(${terms(1)}))" } } /** * Optimization: use BinaryString equals instead of compare. */ def generateStringNotEquals( ctx: CodeGeneratorContext, left: GeneratedExpression, right: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.BOOLEAN, Seq(left, right)) { terms => s"!(${terms.head}.equals(${terms(1)}))" } } def generateSubString( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"${terms.head}.substringSQL(${terms.drop(1).mkString(", ")})" } } def generateLeft( ctx: CodeGeneratorContext, str: GeneratedExpression, len: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, Seq(str, len)) { val emptyString = s"$BINARY_STRING.EMPTY_UTF8" terms => s"${terms(1)} <= 0 ? $emptyString : ${terms.head}.substringSQL(1, ${terms(1)})" } } def generateRight( ctx: CodeGeneratorContext, str: GeneratedExpression, len: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, Seq(str, len)) { terms => s""" |${terms(1)} <= 0 ? | $BINARY_STRING.EMPTY_UTF8 : | ${terms(1)} >= ${terms.head}.numChars() ? | ${terms.head} : | ${terms.head}.substringSQL(-${terms(1)}) """.stripMargin } } def generateCharLength( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.INT, operands) { terms => s"${terms.head}.numChars()" } } def generateSimilarTo( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[SqlFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.BOOLEAN, operands) { terms => s"$className.similar(${toStringTerms(terms, operands)})" } } def generateRegexpExtract( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"$BINARY_STRING.fromString($className.regExpExtract(${ safeToStringTerms(terms, operands)}))" } } def generateRegexpReplace( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.regExpReplace(${toStringTerms(terms, operands)})" } } def generateIsDecimal( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.BOOLEAN, operands) { terms => s"$className.isDecimal(${safeToStringTerms(terms, operands)})" } } def generateIsDigit( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.BOOLEAN, operands) { terms => s"$className.isDigit(${safeToStringTerms(terms, operands)})" } } def generateAscii( ctx: CodeGeneratorContext, str: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.INT, Seq(str)) { terms => s"${terms.head}.numBytes() <= 0 ? 0 : (int) ${terms.head}.getByte(0)" } } def generateIsAlpha( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.BOOLEAN, operands) { terms => s"$className.isAlpha(${safeToStringTerms(terms, operands)})" } } def generateUpper( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"${terms.head}.toUpperCase()" } } def generateLower( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"${terms.head}.toLowerCase()" } } def generateInitcap( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[SqlFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.initcap(${terms.head}.toString())" } } def generatePosition( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.INT, operands) { terms => s"$className.position(${terms.mkString(",")})" } } def generateLocate( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.INT, operands) { terms => s"$className.position(${terms.mkString(",")})" } } def generateInstr( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.INT, operands) { terms => val startPosition = if (operands.length < 3) 1 else terms(2) val nthAppearance = if (operands.length < 4) 1 else terms(3) s"$className.instr(${terms.head}, ${terms(1)}, " + s"$startPosition, $nthAppearance)" } } def generateOverlay( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.overlay(${toStringTerms(terms, operands)})" } } def generateArithmeticConcat( ctx: CodeGeneratorContext, left: GeneratedExpression, right: GeneratedExpression): GeneratedExpression = { generateReturnStringCallIfArgsNotNull(ctx, Seq(left, right)) { terms => s"${terms.head}.toString() + String.valueOf(${terms(1)})" } } def generateLpad( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.lpad(${toStringTerms(terms, operands)})" } } def generateRpad( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.rpad(${toStringTerms(terms, operands)})" } } def generateRepeat( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.repeat(${toStringTerms(terms, operands)})" } } def generateReverse( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"${terms.head}.reverse()" } } def generateReplace( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.replace(${toStringTerms(terms, operands)})" } } def generateSplitIndex( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.splitIndex(${toStringTerms(terms, operands)})" } } def generateKeyValue( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"$className.keyValue(${terms.mkString(",")})" } } def generateHashCode( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.INT, operands) { terms => s"$className.hashCode(${terms.head}.toString())" } } def generateMd5( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = generateHashInternal(ctx, "MD5", operands) def generateHashInternal( ctx: CodeGeneratorContext, algorithm: String, operands: Seq[GeneratedExpression]): GeneratedExpression = { val digestTerm = ctx.addReusableMessageDigest(algorithm) if (operands.length == 1) { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms =>s"${terms.head}.hash($digestTerm)" } } else { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.hash($digestTerm, ${toStringTerms(terms, operands)})" } } } def generateSha1( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = generateHashInternal(ctx, "SHA", operands) def generateSha224( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = generateHashInternal(ctx, "SHA-224", operands) def generateSha256( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = generateHashInternal(ctx, "SHA-256", operands) def generateSha384( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = generateHashInternal(ctx, "SHA-384", operands) def generateSha512( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = generateHashInternal(ctx, "SHA-512", operands) def generateSha2( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName if (operands.last.literal) { val digestTerm = ctx.addReusableSha2MessageDigest(operands.last, nullCheck = true) if (operands.length == 2) { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms =>s"${terms.head}.hash($digestTerm)" } } else { generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.hash($digestTerm," + s"${toStringTerms(terms.dropRight(1), operands.dropRight(1))})" } } } else { if (operands.length == 2) { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"""${terms.head}.hash("SHA-" + ${terms.last})""" } } else { generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => { val strTerms = toStringTerms(terms.dropRight(1), operands.dropRight(1)) s"""$className.hash("SHA-" + ${terms.last}, $strTerms)""" } } } } } def generateParserUrl( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"$BINARY_STRING.fromString($className.parseUrl(${safeToStringTerms(terms, operands)}))" } } def generateFromBase64( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.BYTE_ARRAY, operands) { terms => s"$className.fromBase64(${terms.head}.toString())" } } def generateToBase64( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.toBase64(${terms.head})" } } def generateChr( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[ScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.chr(${terms.head})" } } def generateRegExp( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.BOOLEAN, operands) { terms => s"$className.regExp(${toStringTerms(terms, operands)})" } } def generateJsonValue( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateCallIfArgsNullable(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"$BINARY_STRING.fromString($className.jsonValue(${safeToStringTerms(terms, operands)}))" } } def generateBin( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"Long.toBinaryString(${terms.head})" } } def generateTrim( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => val leading = compareEnum(terms.head, BOTH) || compareEnum(terms.head, LEADING) val trailing = compareEnum(terms.head, BOTH) || compareEnum(terms.head, TRAILING) val args = s"$leading, $trailing, ${terms(1)}" s"${terms(2)}.trim($args)" } } def generateTrimLeft( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"${terms.head}.trimLeft(${terms.drop(1).mkString(", ")})" } } def generateTrimRight( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, operands) { terms => s"${terms.head}.trimRight(${terms.drop(1).mkString(", ")})" } } def generateUuid( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName generateReturnStringCallIfArgsNotNull(ctx, operands) { terms => s"$className.uuid(${terms.mkString(",")})" } } def generateStrToMap( ctx: CodeGeneratorContext, operands: Seq[GeneratedExpression]): GeneratedExpression = { val className = classOf[BuildInScalarFunctions].getCanonicalName val t = new MapType(DataTypes.STRING, DataTypes.STRING) val convertFunc = genToInternal(ctx, t) generateCallIfArgsNotNull(ctx, nullCheck = true, t, operands) { terms => val map = s"$className.strToMap(${toStringTerms(terms, operands)})" s"(${classOf[BinaryMap].getCanonicalName}) ${convertFunc(map)}" } } def generateEncode( ctx: CodeGeneratorContext, str: GeneratedExpression, charset: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.BYTE_ARRAY, Seq(str, charset)) { terms => s"${terms.head}.toString().getBytes(${terms(1)}.toString())" } } def generateDecode( ctx: CodeGeneratorContext, binary: GeneratedExpression, charset: GeneratedExpression): GeneratedExpression = { generateCallIfArgsNotNull(ctx, nullCheck = true, DataTypes.STRING, Seq(binary, charset)) { terms => s"$BINARY_STRING.fromString(new String(${terms.head}, ${terms(1)}.toString()))" } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy