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))));
        }
Beispiel #4
0
 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);
 }
Beispiel #5
0
        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;
Beispiel #9
0
 // 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;