示例#1
0
        public ReaderMapping(IDataRecord dataReader, bool addStartLine, bool addRecNum, bool addEndLine,
                             bool addErrorField)
        {
            var fileReader = dataReader as IFileReader;

            if (fileReader != null)
            {
                ColumnErrorDictionary = new ColumnErrorDictionary(fileReader);
            }

            var readerColumns = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            var fieldCount    = 0;

            for (var col = 0; col < dataReader.FieldCount; col++)
            {
                ImmutableColumn column;
                if (fileReader != null)
                {
                    var icol = fileReader.GetColumn(col);
                    if (icol is ImmutableColumn imcol)
                    {
                        column = imcol;
                    }
                    else
                    {
                        column = new ImmutableColumn(icol.Name, icol.ValueFormat, col, icol.Convert, icol.DestinationName, icol.Ignore, icol.Part, icol.PartSplitter, icol.PartToEnd, icol.TimePart, icol.TimePartFormat, icol.TimeZonePart);
                    }
                }
                else
                {
                    column = new ImmutableColumn(dataReader.GetName(col), new ImmutableValueFormat(dataReader.GetFieldType(col).GetDataType()), col);
                }

                m_ReaderColumnsAll.Add(column.Name);
                if (column.Ignore)
                {
                    continue;
                }
                m_DateTableColumns.Add(column);
                readerColumns.Add(column.Name);
                m_Mapping.Add(col, fieldCount++);
            }

            // add fields
            if (addStartLine && !readerColumns.Contains(ReaderConstants.cStartLineNumberFieldName))
            {
                DataTableStartLine = fieldCount++;
                m_DateTableColumns.Add(new ImmutableColumn(ReaderConstants.cStartLineNumberFieldName,
                                                           new ImmutableValueFormat(DataType.Integer), DataTableStartLine));
            }
            else
            {
                DataTableStartLine = -1;
            }

            if (addRecNum && !readerColumns.Contains(ReaderConstants.cRecordNumberFieldName))
            {
                DataTableRecNum = fieldCount++;
                m_DateTableColumns.Add(new ImmutableColumn(ReaderConstants.cRecordNumberFieldName,
                                                           new ImmutableValueFormat(DataType.Integer), DataTableRecNum));
            }
            else
            {
                DataTableRecNum = -1;
            }

            if (addEndLine && !readerColumns.Contains(ReaderConstants.cEndLineNumberFieldName))
            {
                DataTableEndLine = fieldCount++;
                m_DateTableColumns.Add(new ImmutableColumn(ReaderConstants.cEndLineNumberFieldName,
                                                           new ImmutableValueFormat(DataType.Integer), DataTableEndLine));
            }
            else
            {
                DataTableEndLine = -1;
            }

            if (addErrorField && !readerColumns.Contains(ReaderConstants.cErrorField))
            {
                DataTableErrorField = fieldCount;
                m_DateTableColumns.Add(new ImmutableColumn(ReaderConstants.cErrorField, new ImmutableValueFormat(),
                                                           DataTableErrorField));
            }
            else
            {
                DataTableErrorField = -1;
            }
        }
        /// <summary>
        ///   Gets the column information based on the SQL Source, but overwritten with the definitions
        /// </summary>
        /// <param name="generalFormat">
        ///   general value format for not explicitly specified columns format
        /// </param>
        /// <param name="columnDefinitions"></param>
        /// <param name="sourceSchemaDataReader">The reader for the source.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">reader</exception>
        public static IEnumerable <IColumn> GetColumnInformation(IValueFormat generalFormat,
                                                                 IReadOnlyCollection <IColumn> columnDefinitions, DataTable schemaTable)
        {
            if (schemaTable == null)
            {
                throw new ArgumentNullException(nameof(schemaTable));
            }
            var result = new List <WriterColumn>();

            var colName = new BiDirectionalDictionary <int, string>();

            // Make names unique and fill the dictionary
            foreach (DataRow schemaRow in schemaTable.Rows)
            {
                var colNo   = (int)schemaRow[SchemaTableColumn.ColumnOrdinal];
                var newName =
                    StringUtils.MakeUniqueInCollection(colName.Values, schemaRow[SchemaTableColumn.ColumnName].ToString());

                colName.Add(colNo, newName);
            }

            foreach (DataRow schemaRow in schemaTable.Rows)
            {
                var colNo  = (int)schemaRow[SchemaTableColumn.ColumnOrdinal];
                var column = columnDefinitions.FirstOrDefault(x => x.Name.Equals(colName[colNo], StringComparison.OrdinalIgnoreCase));

                if (column != null && column.Ignore)
                {
                    continue;
                }

                // Based on the data Type in the reader defined and the general format create the value format
                var valueFormat = column?.ValueFormat ?? new ImmutableValueFormat(
                    ((Type)schemaRow[SchemaTableColumn.DataType]).GetDataType(), generalFormat.DateFormat,
                    generalFormat.DateSeparator,
                    generalFormat.TimeSeparator, generalFormat.NumberFormat, generalFormat.GroupSeparator,
                    generalFormat.DecimalSeparator, generalFormat.True,
                    generalFormat.False, generalFormat.DisplayNullAs);

                var fieldLength = Math.Max((int)schemaRow[SchemaTableColumn.ColumnSize], 0);
                switch (valueFormat.DataType)
                {
                case DataType.Integer:
                    fieldLength = 10;
                    break;

                case DataType.Boolean:
                {
                    var lenTrue  = valueFormat.True.Length;
                    var lenFalse = valueFormat.False.Length;
                    fieldLength = lenTrue > lenFalse ? lenTrue : lenFalse;
                    break;
                }

                case DataType.Double:
                case DataType.Numeric:
                    fieldLength = 28;
                    break;

                case DataType.DateTime:
                    fieldLength = valueFormat.DateFormat.Length;
                    break;

                case DataType.Guid:
                    fieldLength = 36;
                    break;

                case DataType.String:
                case DataType.TextToHtml:
                case DataType.TextToHtmlFull:
                case DataType.TextPart:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                var constantTimeZone            = string.Empty;
                var columnOrdinalTimeZoneReader = -1;

                // the timezone information
                if (column != null)
                {
                    var tz = column.TimeZonePart;
                    if (!string.IsNullOrEmpty(tz))
                    {
                        var tzInfo = tz.GetPossiblyConstant();
                        if (tzInfo.Item2)
                        {
                            constantTimeZone = tzInfo.Item1;
                        }
                        else
                        {
                            if (colName.TryGetByValue(tzInfo.Item1, out var ordinal))
                            {
                                columnOrdinalTimeZoneReader = ordinal;
                            }
                        }
                    }
                }
                var ci = new WriterColumn(colName[colNo], colNo, valueFormat, fieldLength, constantTimeZone, columnOrdinalTimeZoneReader);
                result.Add(ci);

                // add an extra column for the time, reading columns they get combined, writing them they
                // get separated again

                if (column == null || string.IsNullOrEmpty(column.TimePart) || colName.ContainsValue(column.TimePart))
                {
                    continue;
                }

                if (ci.ValueFormat.DateFormat.IndexOfAny(new[] { 'h', 'H', 'm', 's' }) != -1)
                {
                    Logger.Warning(
                        $"'{ci.Name}' will create a separate time column '{column.TimePart}' but seems to write time itself '{ci.ValueFormat.DateFormat}'");
                }

                // In case we have a split column, add the second column (unless the column is also present
                result.Add(new WriterColumn(column.TimePart, colNo, new ImmutableValueFormat(DataType.DateTime, column.TimePartFormat, timeSeparator: column.ValueFormat.TimeSeparator), column.TimePartFormat.Length, constantTimeZone, columnOrdinalTimeZoneReader));
            }

            return(result);
        }