private void BuildValuesAsSelectsUnion(IList <SqlField> sourceFields, SqlValuesTable source, IReadOnlyList <ISqlExpression[]> rows) { var columnTypes = new SqlDataType[sourceFields.Count]; for (var i = 0; i < sourceFields.Count; i++) { columnTypes[i] = new SqlDataType(sourceFields[i]); } StringBuilder .AppendLine(); AppendIndent(); for (var i = 0; i < rows.Count; i++) { if (i > 0) { StringBuilder .AppendLine(); AppendIndent(); StringBuilder.AppendLine("\tUNION ALL"); AppendIndent(); } // build record select StringBuilder.Append("\tSELECT "); var row = rows[i]; for (var j = 0; j < row.Length; j++) { var value = row[j]; if (j > 0) { StringBuilder.Append(InlineComma); } if (IsSqlValuesTableValueTypeRequired(source, rows, i, j)) { BuildTypedExpression(columnTypes[j], value); } else { BuildExpression(value); } // add aliases only for first row if (RequiresConstantColumnAliases || i == 0) { StringBuilder.Append(" AS "); Convert(StringBuilder, sourceFields[j].PhysicalName, ConvertType.NameToQueryField); } } if (FakeTable != null) { StringBuilder.Append(" FROM "); BuildFakeTableName(); } } }
protected override bool MergeSourceValueTypeRequired(SqlValuesTable sourceEnumerable, int row, int column) { /* DB2 doesn't like NULLs without type information * : ERROR [42610] [IBM][DB2/NT64] SQL0418N The statement was not processed because the statement * contains an invalid use of one of the following: an untyped parameter marker, the DEFAULT keyword * , or a null value. * * See https://stackoverflow.com/questions/13381898 * * Unfortunatelly, just use typed parameter doesn't help * * To fix it we need to cast at least one NULL in column if all column values are null. * We will do it for last row, when we know that there is no non-null values in column and type hint * needed. * * One thing I don't like is that in some cases DB2 can process query without type hints */ if (row == -1) { return(true); } if (row != 0) { return(false); } // check if column contains NULL in all rows return(sourceEnumerable.Rows.All(r => r[column] is SqlValue value && value.Value == null)); }
protected override bool MergeSourceValueTypeRequired(SqlValuesTable source, IReadOnlyList <ISqlExpression[]> rows, int row, int column) { if (row == -1) { return(true); } var expr = rows[row][column]; if (!MergeSourceValueTypeRequired(expr)) { return(false); } //Base DB2 impl follows // empty source (single row with all values == NULL) if (row == -1) { return(true); } // we add type hints to first row only if (row != 0) { return(false); } // add type hint only if column contains NULL in all rows return(rows.All(r => r[column] is SqlValue value && (value.Value == null || (value is INullable nullable && nullable.IsNull)))); }
public EnumerableContext(ExpressionBuilder builder, BuildInfo buildInfo, SelectQuery query, Type elementType, Expression source) { Parent = buildInfo.Parent; Builder = builder; Expression = buildInfo.Expression; SelectQuery = query; _elementType = elementType; _entityDescriptor = Builder.MappingSchema.GetEntityDescriptor(elementType); Table = new SqlValuesTable(source); }
public EnumerableContext(ExpressionBuilder builder, BuildInfo buildInfo, SelectQuery query, Type elementType) { Parent = buildInfo.Parent; Builder = builder; Expression = buildInfo.Expression; SelectQuery = query; _elementType = elementType; _entityDescriptor = Builder.MappingSchema.GetEntityDescriptor(elementType); Table = BuildValuesTable(); foreach (var field in Table.Fields) { SelectQuery.Select.AddNew(field); } SelectQuery.From.Table(Table); }
protected override bool MergeSourceValueTypeRequired(SqlValuesTable source, IReadOnlyList <ISqlExpression[]> rows, int row, int column) { if (row == 0) { // without type Firebird with convert string values in column to CHAR(LENGTH_OF_BIGGEST_VALUE_IN_COLUMN) with // padding shorter values with spaces if (rows.Any(r => r[column] is SqlValue value && value.Value is string)) { _typedColumns.Add(Tuple.Create(source, column)); return(rows[0][column] is SqlValue val && val.Value != null); } return(false); } return(_typedColumns.Contains(Tuple.Create(source, column)) && rows[row][column] is SqlValue sqlValue && sqlValue.Value != null); }
protected override bool MergeSourceValueTypeRequired(SqlValuesTable source, IReadOnlyList<ISqlExpression[]> rows, int row, int column) { if (row == -1) { return true; } var expr = rows[row][column]; if (MergeSourceValueTypeRequired(expr)) { return true; } switch (row) { case -1: return true; default: return false; case 0: return rows.All(delegate (ISqlExpression[] r) { var sqlValue = r[column] as SqlValue; return sqlValue != null && (sqlValue.Value == null || ((sqlValue as INullable)?.IsNull ?? false)); }); } }
// Informix is too lazy to infer types itself from context protected override bool MergeSourceValueTypeRequired(SqlValuesTable sourceEnumerable, int row, int column) => true;
// Informix is too lazy to infer types itself from context protected override bool IsSqlValuesTableValueTypeRequired(SqlValuesTable source, IReadOnlyList <ISqlExpression[]> rows, int row, int column) => true;
/// <summary> /// Checks that value in specific row and column in enumerable source requires type information generation. /// </summary> /// <param name="source">Merge source table.</param> /// <param name="rows">Merge source data.</param> /// <param name="row">Index of data row to check. Could contain -1 to indicate that this is a check for empty source NULL value.</param> /// <param name="column">Index of data column to check in row.</param> /// <returns>Returns <c>true</c>, if generated SQL should include type information for value at specified position, otherwise <c>false</c> returned.</returns> protected virtual bool IsSqlValuesTableValueTypeRequired(SqlValuesTable source, IReadOnlyList <ISqlExpression[]> rows, int row, int column) => false;