Class: SqlServerDts::RawFile
- Inherits:
-
Object
- Object
- SqlServerDts::RawFile
- Defined in:
- lib/sql_server_raw_file.rb
Overview
SqlServerDts::RawFile class
Defined Under Namespace
Classes: Error, FieldsNotExistsError, UnknownDataTypeError, UnsupportedRawVersionError
Constant Summary collapse
- DEFAULT_RAW_FILE_ENCODING =
default encoding of raw file: ‘utf-16le’
'utf-16le'- DEFAULT_ENCODING =
default encoding of module environment: ‘utf-8’
'utf-8'- SUPPORTED_RAW_VERSIONS =
supported versions of Raw File:
00.90.00.00 => 9 (SQL Server: 9,10) 00.10.01.00 => 10 (SQL Server: 11,12) %w(00.10.01.00 00.90.00.00)
Instance Method Summary collapse
-
#close ⇒ Object
close io-stream.
-
#eof? ⇒ Boolean
check io-stream eof.
-
#header ⇒ Array
get metadata (header) of raw file.
-
#initialize(io, init_pos = nil) ⇒ SqlServerDts::RawFile, [SqlServerDts::RawFile,IO]
constructor
initialization.
-
#pos ⇒ Object
get current position in inner io-stream object.
-
#read_header ⇒ Object
read metadata (header) raw file and fill inner array of metadata.
-
#read_line ⇒ Hash
read line of raw data.
-
#version ⇒ Object
get version of raw file.
Constructor Details
#initialize(io, init_pos = nil) ⇒ SqlServerDts::RawFile, [SqlServerDts::RawFile,IO]
initialization
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/sql_server_raw_file.rb', line 40 def initialize(io,init_pos=nil) if io.is_a?(IO) @raw_io = io @raw_io.binmode unless @raw_io.binmode? read_header @raw_io.seek(init_pos || @data_pos) else @raw_io = File.new(io,'rb') read_header @raw_io.seek(init_pos || @data_pos) if block_given? begin yield [self,@raw_io] ensure @raw_io.close end else self end end end |
Instance Method Details
#close ⇒ Object
close io-stream
197 198 199 |
# File 'lib/sql_server_raw_file.rb', line 197 def close @raw_io.close unless @raw_io.closed? end |
#eof? ⇒ Boolean
check io-stream eof
202 203 204 |
# File 'lib/sql_server_raw_file.rb', line 202 def eof? @raw_io.eof? end |
#header ⇒ Array
get metadata (header) of raw file
187 188 189 |
# File 'lib/sql_server_raw_file.rb', line 187 def header @fields_info end |
#pos ⇒ Object
get current position in inner io-stream object
207 208 209 |
# File 'lib/sql_server_raw_file.rb', line 207 def pos @raw_io.pos end |
#read_header ⇒ Object
read metadata (header) raw file and fill inner array of metadata
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/sql_server_raw_file.rb', line 63 def read_header raise IOError, 'Stream is closed' if @raw_io.closed? begin @raw_io.rewind @version = @raw_io.read(4).unpack('H2H2H2H2').join('.') raise UnsupportedRawVersionError, "Version #{@version} unsupported " unless SUPPORTED_RAW_VERSIONS.include?(@version) @fields_info = [] fields_count = @raw_io.read(4).unpack('I')[0] raise FieldsNotExistsError, 'Fields not exists (fields_count=0)' if fields_count==0 @nil_mask_len = fields_count/8+(fields_count-fields_count/8*8>0?1:0) fields_count.times { name_len = @raw_io.read(4).unpack('I')[0] field_name = @raw_io.read(name_len*2).encode(DEFAULT_ENCODING,DEFAULT_RAW_FILE_ENCODING,{ invalid: :replace, undef: :replace }) (@version == '00.10.01.00') ? values_arr = @raw_io.read(40).unpack('I4iI5') : values_arr = @raw_io.read(32).unpack('I4iI3') field_info = { name: field_name, data_type: values_arr[0], max_length: values_arr[1], p2: values_arr[2], p3: values_arr[3], p4: values_arr[4], precision: values_arr[5], scale: values_arr[6], code_page: values_arr[7], p8: values_arr[8], p9: values_arr[9] } @fields_info << field_info } rescue raise else @data_pos = @raw_io.pos end end |
#read_line ⇒ Hash
read line of raw data
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/sql_server_raw_file.rb', line 104 def read_line raise IOError, 'Stream is closed' if @raw_io.closed? begin nil_mask = @raw_io.read(@nil_mask_len).unpack('b*')[0].each_char.to_a data_row = [] @fields_info.each_with_index { |field_info, index| field_value = if nil_mask[index] == '1' nil else case field_info[:data_type] when 2 # smallint @raw_io.read(get_len(field_info)).unpack('s')[0] when 3 # int, NULL w/o cast @raw_io.read(get_len(field_info)).unpack('i')[0] when 4 # real (float(24)) @raw_io.read(get_len(field_info)).unpack('f')[0] when 5 # float @raw_io.read(get_len(field_info)).unpack('d')[0] when 6 # money (decimal(19,4)), smallmoney ((decimal(10,4))) values_arr = @raw_io.read(get_len(field_info)).unpack('q') "#{values_arr[0].to_s.insert((values_arr[0].to_s.length-4), '.')}" when 11 # bit (@raw_io.read(get_len(field_info)).unpack('B')[0] == '1') ? true : false when 17 # tinyint @raw_io.read(get_len(field_info)).unpack('C')[0] when 20 # bigint @raw_io.read(get_len(field_info)).unpack('q')[0] when 72 # uniqueidentifier uid_arr = @raw_io.read(get_len(field_info)).unpack('H2'*get_len(field_info)) uid_arr[0..3].reverse.join+'-'+uid_arr[4..5].reverse.join+'-'+uid_arr[6..7].reverse.join+'-'+uid_arr[8..9].join+'-'+uid_arr[10..-1].join when 128 # varbinary, binary, timestamp data_len = get_len @raw_io.read(data_len).unpack('H2'*data_len).join when 129 # varchar, char data_len = get_len @raw_io.read(data_len).encode({invalid: :replace, undef: :replace}) when 130 # nvarchar, nchar @raw_io.read(get_len*2).encode(DEFAULT_ENCODING, DEFAULT_RAW_FILE_ENCODING, {invalid: :replace, undef: :replace}) when 131 # numeric, decimal # precision, scale, sign, value values_arr = @raw_io.read(get_len(field_info)).unpack('C3Q') "#{('-' if values_arr[2] == 0)}#{values_arr[3].to_s.insert((values_arr[3].to_s.length-values_arr[1]), '.')}" when 133 # date values_arr = @raw_io.read(get_len(field_info)).unpack('S3') Date.new(values_arr[0], values_arr[1], values_arr[2]) when 135 # datetime, smalldatetime values_arr = @raw_io.read(get_len(field_info)).unpack('S6I') Time.local(values_arr[0], values_arr[1], values_arr[2], values_arr[3], values_arr[4], "#{values_arr[5]}.#{values_arr[6]}".to_f).strftime('%F %T.%L') when 145 # time values_arr = @raw_io.read(10).unpack('S3I') Time.local(Time.now.year, Time.now.month, Time.now.day, values_arr[0], values_arr[1], "#{values_arr[2]}.#{values_arr[3]}".to_f).strftime("%T.%#{field_info[:scale]}N") when 146 # datetimeoffset values_arr = @raw_io.read(get_len(field_info)).unpack('S6Is2') Time.new(values_arr[0], values_arr[1], values_arr[2], values_arr[3], values_arr[4], "#{values_arr[5]}.#{values_arr[6]}".to_f,format('%+03d:%02d',values_arr[7],values_arr[8].abs)).strftime("%F %T.%#{field_info[:scale]}N%:z") when 304 # datetime2 values_arr = @raw_io.read(get_len(field_info)).unpack('S6I') Time.local(values_arr[0], values_arr[1], values_arr[2], values_arr[3], values_arr[4], "#{values_arr[5]}.#{values_arr[6]}".to_f).strftime("%F %T.%#{field_info[:scale]}N") else raise UnknownDataTypeError, "Unknown data type #{field_info[:data_type]}" end end data_row << [ field_info[:name], field_value ] } rescue raise else data_row.to_h end end |
#version ⇒ Object
get version of raw file
192 193 194 |
# File 'lib/sql_server_raw_file.rb', line 192 def version @version end |