OmniSciDB  f17484ade4
 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 30 of file HeavyDBTypeCoercion.java.

Constructor & Destructor Documentation

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

Definition at line 31 of file HeavyDBTypeCoercion.java.

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

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 102 of file HeavyDBTypeCoercion.java.

References 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().

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

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

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

491  {
492  if (binOp.getKind() == SqlKind.AS) {
493  binOp = binOp.operand(0);
494  }
495  coerceOperandType(scope, binOp, 0, targetType);
496  coerceOperandType(scope, binOp, 1, targetType);
497  }

+ 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 297 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().

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

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

252  {
253  boolean coerced = false;
254  final List<ExtArgumentType> paramTypes = udtf.getArgTypes();
255  SqlCall permutedCall = callBinding.permutedCall();
256  for (int i = 0; i < permutedCall.operandCount(); i++) {
257  SqlNode operand = permutedCall.operand(i);
258  if (operand.getKind() == SqlKind.DEFAULT) {
259  // DEFAULT operands don't need to be coerced, they will be filled in by
260  // appropriately typed constants later
261  continue;
262  }
263 
264  RelDataType actualRelType = validator.deriveType(callBinding.getScope(), operand);
265 
266  if (actualRelType.getSqlTypeName() == SqlTypeName.CURSOR) {
267  SqlCall cursorCall = (SqlCall) operand;
269  callBinding.getScope(), permutedCall, i, cursorCall.operand(0), udtf);
270  }
271 
272  RelDataType formalRelType = toRelDataType(paramTypes.get(i), factory);
273  if (actualRelType != formalRelType) {
274  if (SqlTypeUtil.isInterval(actualRelType)
275  && SqlTypeUtil.isInterval(formalRelType)) {
276  IntervalSqlType actualInterval = (IntervalSqlType) actualRelType;
277  IntervalSqlType formalInterval = (IntervalSqlType) formalRelType;
278  if (actualInterval.getIntervalQualifier().isYearMonth()
279  == formalInterval.getIntervalQualifier().isYearMonth()) {
280  continue;
281  }
282  }
283  RelDataType widerType = getWiderTypeForTwo(actualRelType, formalRelType, false);
284  if (!SqlTypeUtil.isTimestamp(widerType)
285  && SqlTypeUtil.sameNamedType(formalRelType, actualRelType)) {
286  // TIMESTAMPs of different precision need coercion, but other structurally equal
287  // types do not (i.e VARCHAR(1) and VARCHAR(10))
288  continue;
289  }
290  coerced = coerceOperandType(callBinding.getScope(), permutedCall, i, widerType)
291  || coerced;
292  }
293  }
294  return coerced;
295  }
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 457 of file HeavyDBTypeCoercion.java.

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

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

+ 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 233 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().

234  {
235  RelDataType returnType = super.getWiderTypeForTwo(type1, type2, stringPromotion);
236  if (SqlTypeUtil.isTimestamp(type1) && SqlTypeUtil.isTimestamp(type2)) {
237  returnType = (type1.getPrecision() > type2.getPrecision()) ? type1 : type2;
238  } else if ((SqlTypeUtil.isDouble(type1) || SqlTypeUtil.isDouble(type2))
239  && (SqlTypeUtil.isApproximateNumeric(type1)
240  && SqlTypeUtil.isApproximateNumeric(type2))) {
241  returnType = factory.createTypeWithNullability(
242  factory.createSqlType(SqlTypeName.DOUBLE), true);
243  }
244  return returnType;
245  }

+ 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 396 of file HeavyDBTypeCoercion.java.

397  {
398  RelDataType fromType = validator.deriveType(scope, node);
399  // This depends on the fact that type validate happens before coercion.
400  // We do not have inferred type for some node, i.e. LOCALTIME.
401  if (fromType == null) {
402  return false;
403  }
404 
405  // This prevents that we cast a JavaType to normal RelDataType.
406  if (fromType instanceof RelDataTypeFactoryImpl.JavaType
407  && toType.getSqlTypeName() == fromType.getSqlTypeName()) {
408  return false;
409  }
410 
411  // Do not make a cast when we don't know specific type (ANY) of the origin node.
412  if (toType.getSqlTypeName() == SqlTypeName.ANY
413  || fromType.getSqlTypeName() == SqlTypeName.ANY) {
414  return false;
415  }
416 
417  // No need to cast between char and varchar.
418  if (SqlTypeUtil.isCharacter(toType) && SqlTypeUtil.isCharacter(fromType)) {
419  return false;
420  }
421 
422  // Implicit type coercion does not handle nullability.
423  if (SqlTypeUtil.equalSansNullability(factory, fromType, toType)) {
424  return false;
425  }
426  // Should keep sync with rules in SqlTypeCoercionRule.
427  assert SqlTypeUtil.canCastFrom(toType, fromType, true);
428  return true;
429  }
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 507 of file HeavyDBTypeCoercion.java.

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

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

+ 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 434 of file HeavyDBTypeCoercion.java.

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

435  {
436  SqlNode operand = selectNode.getSelectList().get(operandIndex);
437  RelDataType newType = validator.getValidatedNodeType(operand);
438  if (operand instanceof SqlCall) {
439  SqlCall asCall = (SqlCall) operand;
440  if (asCall.getOperator().getKind() == SqlKind.AS) {
441  newType = validator.getValidatedNodeType(asCall.operand(0));
442  }
443  }
444  RelDataTypeField oldTypeField =
445  validator.getValidatedNodeType(selectNode).getFieldList().get(operandIndex);
446  RelDataTypeField newTypeField = new RelDataTypeFieldImpl(
447  oldTypeField.getName(), oldTypeField.getIndex(), newType);
448  typeList.add(newTypeField);
449  }

+ Here is the caller graph for this function:


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