OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
com.mapd.calcite.parser.HeavyDBTypeCoercion Class Reference
+ Inheritance diagram for com.mapd.calcite.parser.HeavyDBTypeCoercion:
+ Collaboration diagram for com.mapd.calcite.parser.HeavyDBTypeCoercion:

Public Member Functions

 HeavyDBTypeCoercion (RelDataTypeFactory typeFactory, SqlValidator validator)
 
int calculateTypeCoercionScore (SqlCallBinding callBinding, ExtTableFunction udtf)
 
RelDataType getWiderTypeForTwo (RelDataType type1, RelDataType type2, boolean stringPromotion)
 
boolean extTableFunctionTypeCoercion (SqlCallBinding callBinding, ExtTableFunction udtf)
 

Protected Member Functions

boolean needToCast (SqlValidatorScope scope, SqlNode node, RelDataType toType)
 

Private Member Functions

int calculateScoreForCursorOperand (SqlNode cursorOperand, int index, SqlValidatorScope scope, ExtTableFunction udtf)
 
void coerceCursorType (SqlValidatorScope scope, SqlCall call, int index, SqlNode cursorOperand, ExtTableFunction udtf)
 
void updateValidatedType (List< RelDataTypeField > typeList, SqlSelect selectNode, int operandIndex)
 
int getScoreForTypes (RelDataType targetType, RelDataType originalType, boolean isCursorArgument)
 
void coerceBinOpOperand (SqlBasicCall binOp, RelDataType targetType, SqlValidatorScope scope)
 
boolean shouldCoerceBinOpOperand (SqlNode op, RelDataType targetType, SqlValidatorScope scope)
 

Detailed Description

Definition at line 31 of file HeavyDBTypeCoercion.java.

Constructor & Destructor Documentation

com.mapd.calcite.parser.HeavyDBTypeCoercion.HeavyDBTypeCoercion ( RelDataTypeFactory  typeFactory,
SqlValidator  validator 
)
inline

Definition at line 32 of file HeavyDBTypeCoercion.java.

32  {
33  super(typeFactory, validator);
34  }

Member Function Documentation

int com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateScoreForCursorOperand ( SqlNode  cursorOperand,
int  index,
SqlValidatorScope  scope,
ExtTableFunction  udtf 
)
inlineprivate

Calculates a type coercion score for a single CURSOR() operand. CURSORS need special logic because their underlying types are composite types of one or multiple columns.

Definition at line 103 of file HeavyDBTypeCoercion.java.

References com.mapd.parser.server.ExtensionFunction.ExtArgumentType.Cursor, com.mapd.calcite.parser.HeavyDBSqlOperatorTable.ExtTableFunction.getArgTypes(), com.mapd.calcite.parser.HeavyDBTypeCoercion.getScoreForTypes(), com.mapd.calcite.parser.HeavyDBTypeCoercion.getWiderTypeForTwo(), score, and com.mapd.calcite.parser.HeavyDBTypeCoercion.shouldCoerceBinOpOperand().

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateTypeCoercionScore().

106  {
107  int score = 0;
108 
109  String formalOperandName = udtf.getExtendedParamNames().get(index);
110  List<ExtArgumentType> formalFieldTypes =
111  udtf.getCursorFieldTypes().get(formalOperandName);
112 
113  // If we are typechecking a CURSOR parameter for an overload where this parameter is
114  // not a CURSOR/Column type, then it can never typecheck.
115  if (udtf.getArgTypes().get(index) != ExtArgumentType.Cursor) {
116  return -1;
117  }
118 
119  if (formalFieldTypes == null || formalFieldTypes.size() == 0) {
120  System.out.println(
121  "Warning: UDTF has no CURSOR field subtype data. Proceeding assuming CURSOR typechecks.");
122  // penalize implementations without subtype data, to favor ones that have better
123  // type matches
124  return 1000;
125  }
126 
127  switch (cursorOperand.getKind()) {
128  case SELECT: {
129  SqlSelect selectNode = (SqlSelect) cursorOperand;
130 
131  int iFormal = 0, iActual = 0;
132  for (; iActual < selectNode.getSelectList().size()
133  && iFormal < formalFieldTypes.size();
134  iActual++, iFormal++) {
135  SqlNode selectOperand = selectNode.getSelectList().get(iActual);
136  ExtArgumentType extType = formalFieldTypes.get(iFormal);
137  RelDataType formalRelType = toRelDataType(extType, factory);
138  RelDataType actualRelType = factory.createTypeWithNullability(
139  validator.deriveType(scope, selectOperand), true);
140  RelDataType widerType = getWiderTypeForTwo(formalRelType, actualRelType, false);
141 
142  if (formalRelType.getSqlTypeName() == SqlTypeName.COLUMN_LIST) {
143  ExtArgumentType colListSubtype = getValueType(extType);
144  RelDataType formalSubtype = toRelDataType(colListSubtype, factory);
145 
146  if (isArrayType(colListSubtype)
147  && actualRelType.getSqlTypeName() == SqlTypeName.ARRAY) {
148  ArraySqlType formalArrayType = (ArraySqlType) formalSubtype;
149  ArraySqlType actualArrayType = (ArraySqlType) actualRelType;
150  if (!SqlTypeUtil.sameNamedType(formalArrayType.getComponentType(),
151  actualArrayType.getComponentType())) {
152  // Arrays are not castable, so arrays whose underlying types don't match
153  // can fail early
154  return -1;
155  }
156  }
157 
158  widerType = getWiderTypeForTwo(actualRelType, formalSubtype, false);
159  if (!SqlTypeUtil.sameNamedType(actualRelType, formalSubtype)) {
160  if (widerType == null || widerType == actualRelType) {
161  // no common type, or actual type is wider than formal
162  return -1;
163  }
164  }
165 
166  int colListSize = 0;
167  int numFormalArgumentsLeft = (formalFieldTypes.size() - 1) - iFormal;
168  int maxColListSize =
169  selectNode.getSelectList().size() - numFormalArgumentsLeft - iActual;
170  while (colListSize < maxColListSize) {
171  SqlNode curOperand = selectNode.getSelectList().get(iActual + colListSize);
172  actualRelType = scope.getValidator().deriveType(scope, curOperand);
173  widerType = getWiderTypeForTwo(formalSubtype, actualRelType, false);
174  if (!SqlTypeUtil.sameNamedType(actualRelType, formalSubtype)) {
175  if (widerType == null
176  || !SqlTypeUtil.sameNamedType(widerType, formalSubtype)) {
177  // no common type, or actual type is wider than formal
178  break;
179  } else if (widerType != formalSubtype) {
180  // formal subtype is narrower than widerType, we do not support
181  // downcasting
182  break;
183  } else {
184  score += getScoreForTypes(widerType, actualRelType, true);
185  }
186  } else {
187  // Calcite considers the result of some binary operations as a wider type,
188  // even though they're not passed to the backend as such (FLOAT + literal
189  // == DOUBLE, for instance). We penalize these so that literal operands
190  // are casted regardless. (See QE-788)
191  score += shouldCoerceBinOpOperand(curOperand, widerType, scope) ? 100 : 0;
192  }
193  colListSize++;
194  }
195  iActual += colListSize - 1;
196  } else if (actualRelType != formalRelType) {
197  if (widerType == null) {
198  // no common wider type
199  return -1;
200  } else if (!SqlTypeUtil.isTimestamp(widerType)
201  && SqlTypeUtil.sameNamedType(formalRelType, actualRelType)) {
202  // TIMESTAMPs of different precision need coercion, but other structurally
203  // equal types do not (i.e VARCHAR(1) and VARCHAR(10))
204  continue;
205  } else if (actualRelType == widerType
206  || !SqlTypeUtil.sameNamedType(widerType, formalRelType)) {
207  // formal type is narrower than widerType or the provided actualType, we do
208  // not support downcasting
209  return -1;
210  } else {
211  score += getScoreForTypes(widerType, actualRelType, true);
212  }
213  } else {
214  // Calcite considers the result of some binary operations as a wider type,
215  // even though they're not passed to the backend as such (FLOAT + literal
216  // == DOUBLE, for instance). We penalize these so that literal operands
217  // are casted regardless. (See QE-788)
218  score += shouldCoerceBinOpOperand(selectOperand, widerType, scope) ? 100 : 0;
219  }
220  }
221 
222  if (iActual < selectNode.getSelectList().size()) {
223  return -1;
224  }
225  return score;
226  }
227  default: {
228  System.out.println("Unsupported subquery kind in UDTF CURSOR input argument: "
229  + cursorOperand.getKind());
230  return -1;
231  }
232  }
233  }
boolean shouldCoerceBinOpOperand(SqlNode op, RelDataType targetType, SqlValidatorScope scope)
int getScoreForTypes(RelDataType targetType, RelDataType originalType, boolean isCursorArgument)
RelDataType getWiderTypeForTwo(RelDataType type1, RelDataType type2, boolean stringPromotion)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateTypeCoercionScore ( SqlCallBinding  callBinding,
ExtTableFunction  udtf 
)
inline

Calculates a type coercion score for a given call to a User-Defined Table Function, assuming the call is bound to overload . This is used to perform overload resolution and type checking while considering implicit type coercions are performed (automatic casting of input scalar/columnar arguments).

Definition at line 42 of file HeavyDBTypeCoercion.java.

References com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateScoreForCursorOperand(), com.mapd.calcite.parser.HeavyDBTypeCoercion.getScoreForTypes(), com.mapd.calcite.parser.HeavyDBTypeCoercion.getWiderTypeForTwo(), and score.

Referenced by com.mapd.calcite.parser.ExtTableFunctionTypeChecker.checkOperandTypes().

43  {
44  final List<ExtArgumentType> paramTypes = udtf.getArgTypes();
45  SqlCall permutedCall = callBinding.permutedCall();
46  assert paramTypes != null;
47  int score = 0;
48  for (int i = 0; i < permutedCall.operandCount(); i++) {
49  SqlNode operand = permutedCall.operand(i);
50 
51  // DEFAULT operands should always type-check without any casting (they will be
52  // filled in later during sql2rel translation)
53  if (operand.getKind() == SqlKind.DEFAULT) {
54  continue;
55  }
56 
57  RelDataType actualRelType = validator.deriveType(callBinding.getScope(), operand);
58  RelDataType formalRelType = toRelDataType(paramTypes.get(i), factory);
59 
60  if (actualRelType.getSqlTypeName() == SqlTypeName.CURSOR) {
61  SqlCall cursorCall = (SqlCall) operand;
62  int cursorScore = calculateScoreForCursorOperand(
63  cursorCall.operand(0), i, callBinding.getScope(), udtf);
64  if (cursorScore < 0) {
65  return -1;
66  }
67  score += cursorScore;
68  } else if (actualRelType != formalRelType) {
69  if (SqlTypeUtil.isInterval(actualRelType)
70  && SqlTypeUtil.isInterval(formalRelType)) {
71  // intervals only need to match on whether they're YearMonth or Day
72  IntervalSqlType actualInterval = (IntervalSqlType) actualRelType;
73  IntervalSqlType formalInterval = (IntervalSqlType) formalRelType;
74  if (actualInterval.getIntervalQualifier().isYearMonth()
75  == formalInterval.getIntervalQualifier().isYearMonth()) {
76  continue;
77  } else {
78  return -1;
79  }
80  }
81  RelDataType widerType = getWiderTypeForTwo(actualRelType, formalRelType, false);
82  if (widerType == null) {
83  return -1;
84  } else if (!SqlTypeUtil.isTimestamp(widerType)
85  && SqlTypeUtil.sameNamedType(formalRelType, actualRelType)) {
86  // TIMESTAMPs of different precision need coercion, but other structurally equal
87  // types do not (i.e VARCHAR(1) and VARCHAR(10))
88  continue;
89  } else if (actualRelType == widerType) {
90  return -1;
91  } else if (widerType != actualRelType) {
92  score += getScoreForTypes(widerType, actualRelType, false);
93  }
94  }
95  }
96  return score;
97  }
int getScoreForTypes(RelDataType targetType, RelDataType originalType, boolean isCursorArgument)
int calculateScoreForCursorOperand(SqlNode cursorOperand, int index, SqlValidatorScope scope, ExtTableFunction udtf)
RelDataType getWiderTypeForTwo(RelDataType type1, RelDataType type2, boolean stringPromotion)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceBinOpOperand ( SqlBasicCall  binOp,
RelDataType  targetType,
SqlValidatorScope  scope 
)
inlineprivate

Coerces operands of a binary operator to the given .

Definition at line 497 of file HeavyDBTypeCoercion.java.

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceCursorType().

498  {
499  if (binOp.getKind() == SqlKind.AS) {
500  binOp = binOp.operand(0);
501  }
502  coerceOperandType(scope, binOp, 0, targetType);
503  coerceOperandType(scope, binOp, 1, targetType);
504  }

+ Here is the caller graph for this function:

void com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceCursorType ( SqlValidatorScope  scope,
SqlCall  call,
int  index,
SqlNode  cursorOperand,
ExtTableFunction  udtf 
)
inlineprivate

Definition at line 304 of file HeavyDBTypeCoercion.java.

References com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceBinOpOperand(), com.mapd.calcite.parser.HeavyDBTypeCoercion.getWiderTypeForTwo(), com.mapd.calcite.parser.HeavyDBTypeCoercion.shouldCoerceBinOpOperand(), and com.mapd.calcite.parser.HeavyDBTypeCoercion.updateValidatedType().

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.extTableFunctionTypeCoercion().

308  {
309  String formalOperandName = udtf.getExtendedParamNames().get(index);
310  List<ExtArgumentType> formalFieldTypes =
311  udtf.getCursorFieldTypes().get(formalOperandName);
312  if (formalFieldTypes == null || formalFieldTypes.size() == 0) {
313  return;
314  }
315 
316  switch (cursorOperand.getKind()) {
317  case SELECT: {
318  SqlSelect selectNode = (SqlSelect) cursorOperand;
319  int iFormal = 0, iActual = 0;
320  List<RelDataTypeField> newValidatedTypeList = new ArrayList<>();
321  for (; iActual < selectNode.getSelectList().size()
322  && iFormal < formalFieldTypes.size();
323  iFormal++, iActual++) {
324  SqlNode selectOperand = selectNode.getSelectList().get(iActual);
325  ExtArgumentType extType = formalFieldTypes.get(iFormal);
326  RelDataType formalRelType = toRelDataType(extType, factory);
327  RelDataType actualRelType = validator.deriveType(scope, selectOperand);
328  RelDataType widerType = getWiderTypeForTwo(formalRelType, actualRelType, false);
329 
330  if (isColumnArrayType(extType) || isColumnListArrayType(extType)) {
331  // Arrays can't be casted so don't bother trying
332  updateValidatedType(newValidatedTypeList, selectNode, iActual);
333  continue;
334  }
335 
336  if (formalRelType.getSqlTypeName() == SqlTypeName.COLUMN_LIST) {
337  ExtArgumentType colListSubtype = getValueType(extType);
338  RelDataType formalSubtype = toRelDataType(colListSubtype, factory);
339  widerType = getWiderTypeForTwo(actualRelType, formalSubtype, false);
340 
341  int colListSize = 0;
342  int numFormalArgumentsLeft = (formalFieldTypes.size() - 1) - iFormal;
343  int maxColListSize =
344  selectNode.getSelectList().size() - numFormalArgumentsLeft - iActual;
345  while (colListSize < maxColListSize) {
346  SqlNode curOperand = selectNode.getSelectList().get(iActual + colListSize);
347  actualRelType = scope.getValidator().deriveType(scope, curOperand);
348  widerType = getWiderTypeForTwo(formalSubtype, actualRelType, false);
349  if (!SqlTypeUtil.sameNamedType(actualRelType, formalSubtype)) {
350  if (widerType == null) {
351  break;
352  } else if (actualRelType != widerType) {
353  coerceColumnType(scope,
354  selectNode.getSelectList(),
355  iActual + colListSize,
356  widerType);
357  }
358  } else if (shouldCoerceBinOpOperand(curOperand, widerType, scope)) {
359  coerceBinOpOperand((SqlBasicCall) curOperand, widerType, scope);
360  }
361 
363  newValidatedTypeList, selectNode, iActual + colListSize);
364  colListSize++;
365  }
366  iActual += colListSize - 1;
367  } else if (actualRelType != formalRelType) {
368  if (!SqlTypeUtil.isTimestamp(widerType)
369  && SqlTypeUtil.sameNamedType(actualRelType, formalRelType)) {
370  updateValidatedType(newValidatedTypeList, selectNode, iActual);
371  continue;
372  }
373  if (widerType != actualRelType) {
374  coerceColumnType(scope, selectNode.getSelectList(), iActual, widerType);
375  }
376  updateValidatedType(newValidatedTypeList, selectNode, iActual);
377  } else {
378  if (shouldCoerceBinOpOperand(selectOperand, widerType, scope)) {
379  coerceBinOpOperand((SqlBasicCall) selectOperand, widerType, scope);
380  }
381  // keep old validated type for argument that was not coerced
382  updateValidatedType(newValidatedTypeList, selectNode, iActual);
383  }
384  }
385  RelDataType newCursorStructType = factory.createStructType(newValidatedTypeList);
386  RelDataType newCursorType = factory.createTypeWithNullability(newCursorStructType,
387  validator.getValidatedNodeType(selectNode).isNullable());
388  validator.setValidatedNodeType(selectNode, newCursorType);
389  break;
390  }
391  default: {
392  return;
393  }
394  }
395  }
void updateValidatedType(List< RelDataTypeField > typeList, SqlSelect selectNode, int operandIndex)
boolean shouldCoerceBinOpOperand(SqlNode op, RelDataType targetType, SqlValidatorScope scope)
void coerceBinOpOperand(SqlBasicCall binOp, RelDataType targetType, SqlValidatorScope scope)
RelDataType getWiderTypeForTwo(RelDataType type1, RelDataType type2, boolean stringPromotion)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

boolean com.mapd.calcite.parser.HeavyDBTypeCoercion.extTableFunctionTypeCoercion ( SqlCallBinding  callBinding,
ExtTableFunction  udtf 
)
inline

After a call has been bound to the lowest cost overload, this method performs any necessary coercion of input scalar/columnar arguments in the call.

Definition at line 258 of file HeavyDBTypeCoercion.java.

References com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceCursorType(), and com.mapd.calcite.parser.HeavyDBTypeCoercion.getWiderTypeForTwo().

259  {
260  boolean coerced = false;
261  final List<ExtArgumentType> paramTypes = udtf.getArgTypes();
262  SqlCall permutedCall = callBinding.permutedCall();
263  for (int i = 0; i < permutedCall.operandCount(); i++) {
264  SqlNode operand = permutedCall.operand(i);
265  if (operand.getKind() == SqlKind.DEFAULT) {
266  // DEFAULT operands don't need to be coerced, they will be filled in by
267  // appropriately typed constants later
268  continue;
269  }
270 
271  RelDataType actualRelType = validator.deriveType(callBinding.getScope(), operand);
272 
273  if (actualRelType.getSqlTypeName() == SqlTypeName.CURSOR) {
274  SqlCall cursorCall = (SqlCall) operand;
276  callBinding.getScope(), permutedCall, i, cursorCall.operand(0), udtf);
277  }
278 
279  RelDataType formalRelType = toRelDataType(paramTypes.get(i), factory);
280  if (actualRelType != formalRelType) {
281  if (SqlTypeUtil.isInterval(actualRelType)
282  && SqlTypeUtil.isInterval(formalRelType)) {
283  IntervalSqlType actualInterval = (IntervalSqlType) actualRelType;
284  IntervalSqlType formalInterval = (IntervalSqlType) formalRelType;
285  if (actualInterval.getIntervalQualifier().isYearMonth()
286  == formalInterval.getIntervalQualifier().isYearMonth()) {
287  continue;
288  }
289  }
290  RelDataType widerType = getWiderTypeForTwo(actualRelType, formalRelType, false);
291  if (!SqlTypeUtil.isTimestamp(widerType)
292  && SqlTypeUtil.sameNamedType(formalRelType, actualRelType)) {
293  // TIMESTAMPs of different precision need coercion, but other structurally equal
294  // types do not (i.e VARCHAR(1) and VARCHAR(10))
295  continue;
296  }
297  coerced = coerceOperandType(callBinding.getScope(), permutedCall, i, widerType)
298  || coerced;
299  }
300  }
301  return coerced;
302  }
void coerceCursorType(SqlValidatorScope scope, SqlCall call, int index, SqlNode cursorOperand, ExtTableFunction udtf)
RelDataType getWiderTypeForTwo(RelDataType type1, RelDataType type2, boolean stringPromotion)

+ Here is the call graph for this function:

int com.mapd.calcite.parser.HeavyDBTypeCoercion.getScoreForTypes ( RelDataType  targetType,
RelDataType  originalType,
boolean  isCursorArgument 
)
inlineprivate

Returns a coercion score between an input type and a target type to be casted to. Currently we consider cursor arguments as 100x more expensive than scalar arguments. We also consider a 10x cost to cast from integer to floating point types, to favor overloads that conserve precision.

multiplier

Definition at line 464 of file HeavyDBTypeCoercion.java.

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateScoreForCursorOperand(), and com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateTypeCoercionScore().

465  {
466  // we assume casting columns is 100x more expensive than casting scalars
467  int baseScore = isCursorArgument ? 100 : 1;
468  switch (originalType.getSqlTypeName()) {
469  case TINYINT:
470  case SMALLINT:
471  case INTEGER:
472  case BIGINT: {
473  int multiplier = 1;
474  if (SqlTypeUtil.isApproximateNumeric(targetType)) {
475  // should favor keeping integer types over promoting to floating point
476  multiplier = 10;
477  } /* TODO: Re-enable cast to string types after ColumnList binding is resolved
478  else if (SqlTypeUtil.inCharFamily(targetType)) {
479  // promoting to char types should be a last resort
480  multiplier = 1000;
481  }*/
482  return baseScore * multiplier;
483  }
484  default: {
485  // promoting to char types should be a last resort
486  /* TODO: Re-enable cast to string types after ColumnList binding is resolved
487  int multiplier = (SqlTypeUtil.inCharFamily(targetType) ? 1000 : 1);
488  */
489  return baseScore ;
490  }
491  }
492  }

+ Here is the caller graph for this function:

RelDataType com.mapd.calcite.parser.HeavyDBTypeCoercion.getWiderTypeForTwo ( RelDataType  type1,
RelDataType  type2,
boolean  stringPromotion 
)
inline

We overload this to add a few additional useful rules that Calcite does not implement by default: TIMESTAMP() of lower precision should be castable to higher precision DOUBLE should be the widest type for {FLOAT, REAL, DOUBLE}

Definition at line 240 of file HeavyDBTypeCoercion.java.

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateScoreForCursorOperand(), com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateTypeCoercionScore(), com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceCursorType(), and com.mapd.calcite.parser.HeavyDBTypeCoercion.extTableFunctionTypeCoercion().

241  {
242  RelDataType returnType = super.getWiderTypeForTwo(type1, type2, stringPromotion);
243  if (SqlTypeUtil.isTimestamp(type1) && SqlTypeUtil.isTimestamp(type2)) {
244  returnType = (type1.getPrecision() > type2.getPrecision()) ? type1 : type2;
245  } else if ((SqlTypeUtil.isDouble(type1) || SqlTypeUtil.isDouble(type2))
246  && (SqlTypeUtil.isApproximateNumeric(type1)
247  && SqlTypeUtil.isApproximateNumeric(type2))) {
248  returnType = factory.createTypeWithNullability(
249  factory.createSqlType(SqlTypeName.DOUBLE), true);
250  }
251  return returnType;
252  }

+ Here is the caller graph for this function:

boolean com.mapd.calcite.parser.HeavyDBTypeCoercion.needToCast ( SqlValidatorScope  scope,
SqlNode  node,
RelDataType  toType 
)
inlineprotected

We overload this specifically to REMOVE a rule Calcite uses: Calcite will not cast types in the NUMERIC type family across each other. Therefore, with Calcite's default rules, we would not cast INTEGER columns to BIGINT, or FLOAT to DOUBLE.

Definition at line 403 of file HeavyDBTypeCoercion.java.

404  {
405  RelDataType fromType = validator.deriveType(scope, node);
406  // This depends on the fact that type validate happens before coercion.
407  // We do not have inferred type for some node, i.e. LOCALTIME.
408  if (fromType == null) {
409  return false;
410  }
411 
412  // This prevents that we cast a JavaType to normal RelDataType.
413  if (fromType instanceof RelDataTypeFactoryImpl.JavaType
414  && toType.getSqlTypeName() == fromType.getSqlTypeName()) {
415  return false;
416  }
417 
418  // Do not make a cast when we don't know specific type (ANY) of the origin node.
419  if (toType.getSqlTypeName() == SqlTypeName.ANY
420  || fromType.getSqlTypeName() == SqlTypeName.ANY) {
421  return false;
422  }
423 
424  // No need to cast between char and varchar.
425  if (SqlTypeUtil.isCharacter(toType) && SqlTypeUtil.isCharacter(fromType)) {
426  return false;
427  }
428 
429  // Implicit type coercion does not handle nullability.
430  if (SqlTypeUtil.equalSansNullability(factory, fromType, toType)) {
431  return false;
432  }
433  // Should keep sync with rules in SqlTypeCoercionRule.
434  assert SqlTypeUtil.canCastFrom(toType, fromType, true);
435  return true;
436  }
boolean com.mapd.calcite.parser.HeavyDBTypeCoercion.shouldCoerceBinOpOperand ( SqlNode  op,
RelDataType  targetType,
SqlValidatorScope  scope 
)
inlineprivate

Determines if a binary operator's operands need to be coerced explicitly. Calcite considers the output of some binary operators involving literals as a wider type. As a consequence, some operations such as FLOAT + <float_literal> are type-inferenced to DOUBLE, and will typecheck against UDTFs that accept DOUBLE columns. However, these parameters are still sent to the backend as FLOATs. This method identifies these occurrences, so that they can be casted explicitly.

Definition at line 514 of file HeavyDBTypeCoercion.java.

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.calculateScoreForCursorOperand(), and com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceCursorType().

515  {
516  if (op instanceof SqlBasicCall) {
517  SqlBasicCall asCall = (SqlBasicCall) op;
518  if (asCall.getOperator().getKind() == SqlKind.AS) {
519  SqlNode op2 = asCall.operand(0);
520  if (op2 instanceof SqlBasicCall) {
521  asCall = (SqlBasicCall) op2;
522  } else {
523  return false;
524  }
525  }
526  if (asCall.getOperator() instanceof SqlBinaryOperator) {
527  SqlNode lhs = asCall.operand(0);
528  SqlNode rhs = asCall.operand(1);
529  RelDataType lhsType = validator.deriveType(scope, lhs);
530  RelDataType rhsType = validator.deriveType(scope, rhs);
531  // if neither operand is already the wider type, and at least one is a literal,
532  // depending on precedence the result might falsely typecheck as the wider type
533  if (lhsType != targetType && rhsType != targetType
534  && (lhs.getKind() == SqlKind.LITERAL
535  || rhs.getKind() == SqlKind.LITERAL)) {
536  return true;
537  }
538  }
539  }
540  return false;
541  }

+ Here is the caller graph for this function:

void com.mapd.calcite.parser.HeavyDBTypeCoercion.updateValidatedType ( List< RelDataTypeField >  typeList,
SqlSelect  selectNode,
int  operandIndex 
)
inlineprivate

Updates validated type for CURSOR SqlNodes that had their underlying types coerced.

Definition at line 441 of file HeavyDBTypeCoercion.java.

Referenced by com.mapd.calcite.parser.HeavyDBTypeCoercion.coerceCursorType().

442  {
443  SqlNode operand = selectNode.getSelectList().get(operandIndex);
444  RelDataType newType = validator.getValidatedNodeType(operand);
445  if (operand instanceof SqlCall) {
446  SqlCall asCall = (SqlCall) operand;
447  if (asCall.getOperator().getKind() == SqlKind.AS) {
448  newType = validator.getValidatedNodeType(asCall.operand(0));
449  }
450  }
451  RelDataTypeField oldTypeField =
452  validator.getValidatedNodeType(selectNode).getFieldList().get(operandIndex);
453  RelDataTypeField newTypeField = new RelDataTypeFieldImpl(
454  oldTypeField.getName(), oldTypeField.getIndex(), newType);
455  typeList.add(newTypeField);
456  }

+ Here is the caller graph for this function:


The documentation for this class was generated from the following file: