odps_protobuf 0.1.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -10
- data/lib/odps_protobuf.rb +19 -1
- data/lib/odps_protobuf/crc/crc.rb +36 -0
- data/lib/odps_protobuf/crc/lib/linux/crc32c.so +0 -0
- data/lib/odps_protobuf/crc/lib/win/crc32c.so +0 -0
- data/lib/odps_protobuf/crc/origin/crc.rb +129 -0
- data/lib/odps_protobuf/crc/origin/crc32.rb +126 -0
- data/lib/odps_protobuf/crc/origin/crc32c.rb +105 -0
- data/lib/odps_protobuf/deserializer.rb +57 -0
- data/lib/odps_protobuf/field.rb +1 -0
- data/lib/odps_protobuf/field/bool_field.rb +13 -0
- data/lib/odps_protobuf/field/datetime_field.rb +13 -0
- data/lib/odps_protobuf/field/decimal_field.rb +15 -0
- data/lib/odps_protobuf/field/double_field.rb +14 -0
- data/lib/odps_protobuf/field/fixed32_field.rb +13 -0
- data/lib/odps_protobuf/field/fixed64_field.rb +14 -0
- data/lib/odps_protobuf/field/fixed_string_field.rb +14 -0
- data/lib/odps_protobuf/field/sint64_field.rb +23 -0
- data/lib/odps_protobuf/field/string_field.rb +21 -0
- data/lib/odps_protobuf/field/uint32_field.rb +21 -0
- data/lib/odps_protobuf/serializer.rb +135 -0
- data/lib/odps_protobuf/table.rb +155 -0
- data/lib/odps_protobuf/version.rb +1 -1
- metadata +21 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 465f2649c2d0446a126ea79c290507144791b1bf
|
4
|
+
data.tar.gz: 3cfabff435ea2d4414a40380331dbc9cc49e75e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a245fe543ad6ee026dbaf56e58c1e660a735d207ad90e5d70c654e8aa9833d075373e1e8e7d32dec04ec3b2d955b918a98c9402f1505d451dee62ed54c91faca
|
7
|
+
data.tar.gz: 8c8b077630b1fd5f96c4f21f81607311ae5fa2a851e7a81163b32fd50ae18e5dda40f3d66ac06731c1f8821bc8a40dee26fd2db5303e21d10d238b2da28298d6
|
data/README.md
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
# OdpsProtobuf
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
Protobuf for ODPS
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
9
7
|
Add this line to your application's Gemfile:
|
10
8
|
|
11
|
-
|
12
|
-
gem 'odps_protobuf'
|
13
|
-
```
|
9
|
+
gem 'odps_protobuf'
|
14
10
|
|
15
11
|
And then execute:
|
16
12
|
|
@@ -22,11 +18,26 @@ Or install it yourself as:
|
|
22
18
|
|
23
19
|
## Usage
|
24
20
|
|
25
|
-
serializer = Odps::ProtobufSerializer.new
|
26
|
-
serializer.serialize(records, schema) # => serialized string
|
27
21
|
|
28
|
-
|
29
|
-
|
22
|
+
schema = {
|
23
|
+
'columns' => [
|
24
|
+
{ 'name' => 'uuid', 'type' => 'bigint' },
|
25
|
+
{ 'name' => 'name', 'type' => 'string' },
|
26
|
+
{ 'name' => 'price', 'type' => 'decimal' },
|
27
|
+
{ 'name' => 'discount', 'type' => 'double' },
|
28
|
+
{ 'name' => 'in_stock', 'type' => 'boolean' },
|
29
|
+
{ 'name' => 'created_time', 'type' => 'datetime' }
|
30
|
+
]
|
31
|
+
}
|
32
|
+
record1 = [1, 'apple', BigDecimal.new("1.2"), 0.5, true, Time.now]
|
33
|
+
record2 = [1000, 'red apple', BigDecimal.new("12.5"), 0.9, false, Time.now]
|
34
|
+
|
35
|
+
serializer = OdpsProtobuf::Serializer.new
|
36
|
+
|
37
|
+
protobufed_str = serializer.serialize([record1, record2], schema) # => "\b\u0002\u0012\u0005apple\u001A\u00031.2!\u0000\u0000\u0000\u0000\u0000\u0000\xE0?(\u00010\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007F\xCCӥ\xE2\u000F\b\xD0\u000F\u0012\tred apple\u001A\u000412.5!\xCD\xCC\xCC\xCC\xCC\xCC\xEC?(\u00000\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007Fڿ\x9C\xB8\u0006\xF0\xFF\xFF\u007F\u0004\xF8\xFF\xFF\u007F\xE5鞜\u0006"
|
38
|
+
|
39
|
+
deserializer = Odps::ProtobufDeSerializer.new
|
40
|
+
deserializer.deserialize(protobufed_str, schema) # => [[1, "apple", #<BigDecimal:7f94dc9b2a80,'0.12E1',18(18)>, 0.5, true, 2016-01-01 10:00:00 +0800], [1000, "red apple", #<BigDecimal:7f94dc9b2648,'0.125E2',18(18)>, 0.9, false, 2016-01-01 10:00:00 +0800]]
|
30
41
|
|
31
42
|
## Authors && Contributors
|
32
43
|
|
data/lib/odps_protobuf.rb
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
require "odps_protobuf/version"
|
2
|
+
require 'odps_protobuf/field'
|
3
|
+
require 'odps_protobuf/table'
|
4
|
+
require "odps_protobuf/serializer"
|
5
|
+
require "odps_protobuf/deserializer"
|
2
6
|
|
3
7
|
module OdpsProtobuf
|
4
|
-
|
8
|
+
$TUNNEL_META_COUNT = 33_554_430 # magic num 2^25-2
|
9
|
+
$TUNNEL_META_CHECKSUM = 33_554_431 # magic num 2^25-1
|
10
|
+
$TUNNEL_END_RECORD = 33_553_408 # maigc num 2^25-1024
|
11
|
+
|
12
|
+
$ODPS_BIGINT = 'bigint'
|
13
|
+
$ODPS_DOUBLE = 'double'
|
14
|
+
$ODPS_BOOLEAN = 'boolean'
|
15
|
+
$ODPS_DATETIME = 'datetime'
|
16
|
+
$ODPS_STRING = 'string'
|
17
|
+
$ODPS_DECIMAL = 'decimal'
|
18
|
+
|
19
|
+
$STRING_MAX_LENTH = 8 * 1024 * 1024
|
20
|
+
$DATETIME_MAX_TICKS = 253_402_271_999_000
|
21
|
+
$DATETIME_MIN_TICKS = -62_135_798_400_000
|
22
|
+
$STRING_CHARSET = 'UTF-8'
|
5
23
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
module OdpsProtobuf
|
4
|
+
class CrcCalculator
|
5
|
+
# @param [StringIO] data
|
6
|
+
# @return crc32c to_i
|
7
|
+
def self.calculate(data)
|
8
|
+
if !$USE_FAST_CRC
|
9
|
+
require_relative 'origin/crc32c'
|
10
|
+
crc32c = Digest::CRC32c.new
|
11
|
+
crc32c.update(data.string)
|
12
|
+
return crc32c.checksum.to_i
|
13
|
+
elsif getOsType == 'linux' || getOsType == 'unix'
|
14
|
+
require_relative 'lib/odps/linux/crc32c.so'
|
15
|
+
return Crc32c.calculate(data.string, data.length, 0).to_i
|
16
|
+
elsif getOsType == 'windows'
|
17
|
+
require_relative 'lib/odps/win/crc32c.so'
|
18
|
+
return Crc32c.calculate(data.string, data.length, 0).to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.getOsType
|
23
|
+
host_os = RbConfig::CONFIG['host_os']
|
24
|
+
case host_os
|
25
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
26
|
+
'windows'
|
27
|
+
when /linux/
|
28
|
+
'linux'
|
29
|
+
when /solaris|bsd/
|
30
|
+
'unix'
|
31
|
+
else
|
32
|
+
fail Error::WebDriverError, 'unspport os'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#
|
19
|
+
require 'digest'
|
20
|
+
module Digest
|
21
|
+
#
|
22
|
+
# Base class for all CRC algorithms.
|
23
|
+
#
|
24
|
+
class CRC < Digest::Class
|
25
|
+
include Digest::Instance
|
26
|
+
# The initial value of the CRC checksum
|
27
|
+
INIT_CRC = 0x00
|
28
|
+
# The XOR mask to apply to the resulting CRC checksum
|
29
|
+
XOR_MASK = 0x00
|
30
|
+
# The bit width of the CRC checksum
|
31
|
+
WIDTH = 0
|
32
|
+
#
|
33
|
+
# Calculates the CRC checksum.
|
34
|
+
#
|
35
|
+
# @param [String] data
|
36
|
+
# The given data.
|
37
|
+
#
|
38
|
+
# @return [Integer]
|
39
|
+
# The CRC checksum.
|
40
|
+
#
|
41
|
+
def self.checksum(data)
|
42
|
+
crc = new
|
43
|
+
crc << data
|
44
|
+
crc.checksum
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Packs the given CRC checksum.
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
# The packed CRC checksum.
|
52
|
+
#
|
53
|
+
def self.pack(_crc)
|
54
|
+
''
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Initializes the CRC checksum.
|
59
|
+
#
|
60
|
+
def initialize
|
61
|
+
@crc = self.class.const_get(:INIT_CRC)
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# The input block length.
|
66
|
+
#
|
67
|
+
# @return [1]
|
68
|
+
#
|
69
|
+
def block_length
|
70
|
+
1
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# The length of the digest.
|
75
|
+
#
|
76
|
+
# @return [Integer]
|
77
|
+
# The length in bytes.
|
78
|
+
#
|
79
|
+
def digest_length
|
80
|
+
(self.class.const_get(:WIDTH) / 8.0).ceil
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Updates the CRC checksum with the given data.
|
85
|
+
#
|
86
|
+
# @param [String] data
|
87
|
+
# The data to update the CRC checksum with.
|
88
|
+
#
|
89
|
+
def update(_data)
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# @see {#update}
|
94
|
+
#
|
95
|
+
def <<(data)
|
96
|
+
update(data)
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Resets the CRC checksum.
|
102
|
+
#
|
103
|
+
# @return [Integer]
|
104
|
+
# The default value of the CRC checksum.
|
105
|
+
#
|
106
|
+
def reset
|
107
|
+
@crc = self.class.const_get(:INIT_CRC)
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# The resulting CRC checksum.
|
112
|
+
#
|
113
|
+
# @return [Integer]
|
114
|
+
# The resulting CRC checksum.
|
115
|
+
#
|
116
|
+
def checksum
|
117
|
+
@crc ^ self.class.const_get(:XOR_MASK)
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# Finishes the CRC checksum calculation.
|
122
|
+
#
|
123
|
+
# @see {pack}
|
124
|
+
#
|
125
|
+
def finish
|
126
|
+
self.class.pack(checksum)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#
|
19
|
+
require_relative 'crc'
|
20
|
+
module Digest
|
21
|
+
#
|
22
|
+
# Implements the CRC32 algorithm.
|
23
|
+
#
|
24
|
+
class CRC32 < CRC
|
25
|
+
WIDTH = 4
|
26
|
+
INIT_CRC = 0xffffffff
|
27
|
+
XOR_MASK = 0xffffffff
|
28
|
+
# Generated by `./pycrc.py --algorithm=table-driven --model=crc-32 --generate=c`
|
29
|
+
TABLE = [
|
30
|
+
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
31
|
+
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
32
|
+
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
33
|
+
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
34
|
+
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
35
|
+
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
36
|
+
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
37
|
+
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
38
|
+
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
39
|
+
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
40
|
+
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
41
|
+
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
42
|
+
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
43
|
+
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
44
|
+
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
45
|
+
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
46
|
+
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
47
|
+
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
48
|
+
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
49
|
+
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
50
|
+
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
51
|
+
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
52
|
+
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
53
|
+
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
54
|
+
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
55
|
+
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
56
|
+
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
57
|
+
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
58
|
+
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
59
|
+
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
60
|
+
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
61
|
+
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
62
|
+
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
63
|
+
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
64
|
+
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
65
|
+
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
66
|
+
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
67
|
+
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
68
|
+
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
69
|
+
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
70
|
+
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
71
|
+
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
72
|
+
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
73
|
+
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
74
|
+
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
75
|
+
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
76
|
+
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
77
|
+
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
78
|
+
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
79
|
+
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
80
|
+
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
81
|
+
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
82
|
+
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
83
|
+
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
84
|
+
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
85
|
+
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
86
|
+
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
87
|
+
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
88
|
+
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
89
|
+
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
90
|
+
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
91
|
+
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
92
|
+
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
93
|
+
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
94
|
+
]
|
95
|
+
#
|
96
|
+
# Packs the CRC32 checksum.
|
97
|
+
#
|
98
|
+
# @param [Integer] crc
|
99
|
+
# The checksum to pack.
|
100
|
+
#
|
101
|
+
# @return [String]
|
102
|
+
# The packed checksum.
|
103
|
+
#
|
104
|
+
def self.pack(crc)
|
105
|
+
buffer = ''
|
106
|
+
buffer << ((crc & 0xff000000) >> 24).chr
|
107
|
+
buffer << ((crc & 0xff0000) >> 16).chr
|
108
|
+
buffer << ((crc & 0xff00) >> 8).chr
|
109
|
+
buffer << (crc & 0xff).chr
|
110
|
+
buffer
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Updates the CRC32 checksum.
|
115
|
+
#
|
116
|
+
# @param [String] data
|
117
|
+
# The data to update the checksum with.
|
118
|
+
#
|
119
|
+
def update(data)
|
120
|
+
data.each_byte do |b|
|
121
|
+
@crc = (((@crc >> 8) & 0x00ffffff) ^ TABLE[(@crc ^ b) & 0xff])
|
122
|
+
end
|
123
|
+
self
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#
|
19
|
+
require_relative 'crc32'
|
20
|
+
module Digest
|
21
|
+
#
|
22
|
+
# Implements the CRC32c algorithm.
|
23
|
+
#
|
24
|
+
class CRC32c < CRC32
|
25
|
+
# Generated by `./pycrc.py --algorithm=table-driven --model=crc-32c --generate=c`
|
26
|
+
TABLE = [
|
27
|
+
0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
|
28
|
+
0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
|
29
|
+
0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
|
30
|
+
0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
|
31
|
+
0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
|
32
|
+
0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
|
33
|
+
0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
|
34
|
+
0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
|
35
|
+
0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
|
36
|
+
0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
|
37
|
+
0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
|
38
|
+
0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
|
39
|
+
0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
|
40
|
+
0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
|
41
|
+
0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
|
42
|
+
0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
|
43
|
+
0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
|
44
|
+
0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
|
45
|
+
0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
|
46
|
+
0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
|
47
|
+
0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
|
48
|
+
0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
|
49
|
+
0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
|
50
|
+
0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
|
51
|
+
0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
|
52
|
+
0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
|
53
|
+
0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
|
54
|
+
0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
|
55
|
+
0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
|
56
|
+
0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
|
57
|
+
0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
|
58
|
+
0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
|
59
|
+
0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
|
60
|
+
0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
|
61
|
+
0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
|
62
|
+
0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
|
63
|
+
0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
|
64
|
+
0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
|
65
|
+
0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
|
66
|
+
0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
|
67
|
+
0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
|
68
|
+
0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
|
69
|
+
0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
|
70
|
+
0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
|
71
|
+
0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
|
72
|
+
0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
|
73
|
+
0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
|
74
|
+
0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
|
75
|
+
0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
|
76
|
+
0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
|
77
|
+
0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
|
78
|
+
0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
|
79
|
+
0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
|
80
|
+
0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
|
81
|
+
0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
|
82
|
+
0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
|
83
|
+
0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
|
84
|
+
0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
|
85
|
+
0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
|
86
|
+
0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
|
87
|
+
0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
|
88
|
+
0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
|
89
|
+
0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
|
90
|
+
0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
|
91
|
+
]
|
92
|
+
#
|
93
|
+
# Updates the CRC32 checksum.
|
94
|
+
#
|
95
|
+
# @param [String] data
|
96
|
+
# The data to update the checksum with.
|
97
|
+
#
|
98
|
+
def update(data)
|
99
|
+
data.each_byte do |b|
|
100
|
+
@crc = (((@crc >> 8) & 0x00ffffff) ^ TABLE[(@crc ^ b) & 0xff])
|
101
|
+
end
|
102
|
+
self
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module OdpsProtobuf
|
2
|
+
class Deserializer
|
3
|
+
|
4
|
+
# Deserialize protobufed string into decode data
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# protobufed_string = "\b\u0002\u0012\u0005apple\u001A\u00031.2!\u0000\u0000\u0000\u0000\u0000\u0000\xE0?(\u00010\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007F\xCCӥ\xE2\u000F\b\xD0\u000F\u0012\tred apple\u001A\u000412.5!\xCD\xCC\xCC\xCC\xCC\xCC\xEC?(\u00000\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007Fڿ\x9C\xB8\u0006\xF0\xFF\xFF\u007F\u0004\xF8\xFF\xFF\u007F\xE5鞜\u0006"
|
8
|
+
# schema = {
|
9
|
+
# 'columns' => [
|
10
|
+
# { 'name' => 'uuid', 'type' => 'bigint' },
|
11
|
+
# { 'name' => 'name', 'type' => 'string' },
|
12
|
+
# { 'name' => 'price', 'type' => 'decimal' },
|
13
|
+
# { 'name' => 'discount', 'type' => 'double' },
|
14
|
+
# { 'name' => 'in_stock', 'type' => 'boolean' },
|
15
|
+
# { 'name' => 'created_time', 'type' => 'datetime' }
|
16
|
+
# ]
|
17
|
+
# }
|
18
|
+
# deserialize(protobufed_string, schema) #=> [[1, "apple", #<BigDecimal:7f94dc9b2a80,'0.12E1',18(18)>, 0.5, true, 2016-01-01 10:00:00 +0800], [1000, "red apple", #<BigDecimal:7f94dc9b2648,'0.125E2',18(18)>, 0.9, false, 2016-01-01 10:00:00 +0800]]
|
19
|
+
def deserialize(content, schema)
|
20
|
+
stream = StringIO.new(content) unless content.is_a?(StringIO)
|
21
|
+
schema = OdpsTableSchema.new(schema)
|
22
|
+
records = []
|
23
|
+
record = []
|
24
|
+
until stream.eof?
|
25
|
+
key, value = ::Protobuf::Decoder.read_field(stream)
|
26
|
+
#p "key: #{key}, value: #{value}"
|
27
|
+
if key == $TUNNEL_END_RECORD
|
28
|
+
records << record.pop(record.length)
|
29
|
+
else
|
30
|
+
col = schema.mCols[key - 1]
|
31
|
+
break if col.nil?
|
32
|
+
case col.mType
|
33
|
+
when $ODPS_BIGINT
|
34
|
+
record << Sint64Field.decode(value)
|
35
|
+
when $ODPS_DOUBLE
|
36
|
+
record << DoubleField.decode(value)
|
37
|
+
when $ODPS_BOOLEAN
|
38
|
+
#p "key: #{key}, value: #{value}, decoded: #{BoolField.decode(value)}"
|
39
|
+
record << BoolField.decode(value)
|
40
|
+
when $ODPS_DATETIME
|
41
|
+
#p "key: #{key}, value: #{value}, decoded: #{DateTimeField.decode(value)}"
|
42
|
+
record << DateTimeField.decode(value)
|
43
|
+
when $ODPS_STRING
|
44
|
+
#p "key: #{key}, value: #{value}, decoded: #{StringField.decode(value)}"
|
45
|
+
record << StringField.decode(value)
|
46
|
+
when $ODPS_DECIMAL
|
47
|
+
#p "key: #{key}, value: #{value}, decoded: #{StringField.decode(value)}"
|
48
|
+
record << DecimalField.decode(value)
|
49
|
+
else
|
50
|
+
fail 'invalid mType'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
records
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.join(File.dirname(__FILE__), 'field/*.rb')].each { |f| require f }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module OdpsProtobuf
|
2
|
+
class Fixed64Field
|
3
|
+
class << self
|
4
|
+
def encode(value)
|
5
|
+
[value & 0xffff_ffff, value >> 32].pack('VV')
|
6
|
+
end
|
7
|
+
|
8
|
+
def decode(value)
|
9
|
+
unpack_vlaue = value.unpack('VV')
|
10
|
+
(unpack_value[1] << 32) ^ unpack_value[0]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module OdpsProtobuf
|
2
|
+
class Sint64Field
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def encode(value)
|
6
|
+
if value >= 0
|
7
|
+
::Protobuf::Field::VarintField.encode(value << 1)
|
8
|
+
else
|
9
|
+
::Protobuf::Field::VarintField.encode(~(value << 1))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def decode(value)
|
14
|
+
if (value & 1).zero?
|
15
|
+
value >> 1 # positive value
|
16
|
+
else
|
17
|
+
~value >> 1 # negative value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module OdpsProtobuf
|
2
|
+
class StringField
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def encode(value)
|
6
|
+
value_to_encode = value.dup
|
7
|
+
# value_to_encode.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "")
|
8
|
+
value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
|
9
|
+
string_bytes = ::Protobuf::Field::VarintField.encode(value_to_encode.size)
|
10
|
+
string_bytes << value_to_encode
|
11
|
+
end
|
12
|
+
|
13
|
+
def decode(value)
|
14
|
+
bytes_to_decode = value.dup
|
15
|
+
bytes_to_decode.force_encoding(::Protobuf::Field::StringField::ENCODING)
|
16
|
+
bytes_to_decode
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module OdpsProtobuf
|
2
|
+
class Uint32Field
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def encode(value)
|
6
|
+
return [value].pack('C') if value < 128
|
7
|
+
bytes = []
|
8
|
+
until value == 0
|
9
|
+
bytes << (0x80 | (value & 0x7f))
|
10
|
+
value >>= 7
|
11
|
+
end
|
12
|
+
bytes[-1] &= 0x7f
|
13
|
+
bytes.pack('C*')
|
14
|
+
end
|
15
|
+
|
16
|
+
def decode
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require 'protobuf'
|
5
|
+
require 'odps_protobuf/crc/crc'
|
6
|
+
|
7
|
+
module OdpsProtobuf
|
8
|
+
class Serializer
|
9
|
+
|
10
|
+
# Serialize fields with schema
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# schema = {
|
14
|
+
# 'columns' => [
|
15
|
+
# { 'name' => 'uuid', 'type' => 'bigint' },
|
16
|
+
# { 'name' => 'name', 'type' => 'string' },
|
17
|
+
# { 'name' => 'price', 'type' => 'decimal' },
|
18
|
+
# { 'name' => 'discount', 'type' => 'double' },
|
19
|
+
# { 'name' => 'in_stock', 'type' => 'boolean' },
|
20
|
+
# { 'name' => 'created_time', 'type' => 'datetime' }
|
21
|
+
# ]
|
22
|
+
# }
|
23
|
+
# record1 = [1, 'apple', BigDecimal.new("1.2"), 0.5, true, Time.now]
|
24
|
+
# record2 = [1000, 'red apple', BigDecimal.new("12.5"), 0.9, false, Time.now]
|
25
|
+
#
|
26
|
+
# serialize([record1, record2], schema) # => "\b\u0002\u0012\u0005apple\u001A\u00031.2!\u0000\u0000\u0000\u0000\u0000\u0000\xE0?(\u00010\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007F\xCCӥ\xE2\u000F\b\xD0\u000F\u0012\tred apple\u001A\u000412.5!\xCD\xCC\xCC\xCC\xCC\xCC\xEC?(\u00000\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007Fڿ\x9C\xB8\u0006\xF0\xFF\xFF\u007F\u0004\xF8\xFF\xFF\u007F\xE5鞜\u0006"
|
27
|
+
def serialize(records, schema)
|
28
|
+
schema = OdpsTableSchema.new(schema)
|
29
|
+
stream = StringIO.new
|
30
|
+
crc32cPack = StringIO.new
|
31
|
+
|
32
|
+
if records.is_a? Array
|
33
|
+
records.each do |record|
|
34
|
+
record = covert2record(record, schema) unless record.is_a?(OdpsTableRecord)
|
35
|
+
|
36
|
+
crc32cRecord = StringIO.new
|
37
|
+
schema.mCols.each do |col|
|
38
|
+
cellValue = record.getValue(col.mIdx)
|
39
|
+
next if cellValue.nil?
|
40
|
+
crc32cRecord.write(Fixed32Field.encode(col.mIdx + 1))
|
41
|
+
case col.mType
|
42
|
+
when $ODPS_BIGINT
|
43
|
+
crc32cRecord.write(Fixed64Field.encode(cellValue))
|
44
|
+
writeTag(col.mIdx + 1, ::Protobuf::WireType::VARINT, stream)
|
45
|
+
stream.write(Sint64Field.encode(cellValue))
|
46
|
+
when $ODPS_DOUBLE
|
47
|
+
crc32cRecord.write(DoubleField.encode(cellValue))
|
48
|
+
writeTag(col.mIdx + 1, ::Protobuf::WireType::FIXED64, stream)
|
49
|
+
stream.write(DoubleField.encode(cellValue))
|
50
|
+
when $ODPS_BOOLEAN
|
51
|
+
crc32cRecord.write(BoolField.encode(cellValue))
|
52
|
+
writeTag(col.mIdx + 1, ::Protobuf::WireType::VARINT, stream)
|
53
|
+
stream.write(BoolField.encode(cellValue))
|
54
|
+
when $ODPS_DATETIME
|
55
|
+
crc32cRecord.write(Fixed64Field.encode(cellValue))
|
56
|
+
writeTag(col.mIdx + 1, ::Protobuf::WireType::VARINT, stream)
|
57
|
+
stream.write(DateTimeField.encode(cellValue))
|
58
|
+
when $ODPS_STRING
|
59
|
+
crc32cRecord.write(cellValue)
|
60
|
+
writeTag(col.mIdx + 1, ::Protobuf::WireType::LENGTH_DELIMITED, stream)
|
61
|
+
stream.write(StringField.encode(cellValue))
|
62
|
+
when $ODPS_DECIMAL
|
63
|
+
crc32cRecord.write(cellValue)
|
64
|
+
writeTag(col.mIdx + 1, ::Protobuf::WireType::LENGTH_DELIMITED, stream)
|
65
|
+
stream.write(DecimalField.encode(cellValue))
|
66
|
+
else
|
67
|
+
fail 'invalid mType'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
recordCrc = CrcCalculator.calculate(crc32cRecord)
|
71
|
+
#p "TUNNEL_END_RECORD: #{$TUNNEL_END_RECORD}"
|
72
|
+
writeTag($TUNNEL_END_RECORD, ::Protobuf::WireType::VARINT, stream)
|
73
|
+
stream.write(Uint32Field.encode(recordCrc))
|
74
|
+
crc32cPack.write(Fixed32Field.encode(recordCrc))
|
75
|
+
end
|
76
|
+
#p "TUNNEL_META_COUNT: #{$TUNNEL_META_COUNT}"
|
77
|
+
writeTag($TUNNEL_META_COUNT, ::Protobuf::WireType::VARINT, stream)
|
78
|
+
stream.write(Sint64Field.encode(records.size))
|
79
|
+
#p "TUNNEL_META_CHECKSUM: #{$TUNNEL_META_CHECKSUM}"
|
80
|
+
writeTag($TUNNEL_META_CHECKSUM, ::Protobuf::WireType::VARINT, stream)
|
81
|
+
stream.write(Uint32Field.encode(CrcCalculator.calculate(crc32cPack)))
|
82
|
+
else
|
83
|
+
fail 'param must be a array'
|
84
|
+
end
|
85
|
+
|
86
|
+
return stream.string
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def writeTag(idx, type, stream)
|
92
|
+
key = (idx << 3) | type
|
93
|
+
stream << ::Protobuf::Field::VarintField.encode(key)
|
94
|
+
end
|
95
|
+
|
96
|
+
def covert2record(value, schema)
|
97
|
+
fail 'value must be a array' unless value.is_a? Array
|
98
|
+
|
99
|
+
if value.count != schema.getColumnCount
|
100
|
+
fail 'column counts are not equal between value and schema'
|
101
|
+
end
|
102
|
+
|
103
|
+
record = OdpsTableRecord.new(schema)
|
104
|
+
i = 0
|
105
|
+
while i < value.count
|
106
|
+
#p schema, schema.getColumnType(i)
|
107
|
+
type = schema.getColumnType(i)
|
108
|
+
if value[i].nil?
|
109
|
+
record.setNullValue(i)
|
110
|
+
i += 1
|
111
|
+
next
|
112
|
+
end
|
113
|
+
#p type
|
114
|
+
case type
|
115
|
+
when $ODPS_BIGINT
|
116
|
+
record.setBigInt(i, value[i])
|
117
|
+
when $ODPS_BOOLEAN
|
118
|
+
record.setBoolean(i, value[i])
|
119
|
+
when $ODPS_DATETIME
|
120
|
+
record.setDateTime(i, value[i])
|
121
|
+
when $ODPS_DOUBLE
|
122
|
+
record.setDouble(i, value[i])
|
123
|
+
when $ODPS_STRING
|
124
|
+
record.setString(i, value[i])
|
125
|
+
when $ODPS_DECIMAL
|
126
|
+
record.setDecimal(i, value[i])
|
127
|
+
else
|
128
|
+
fail 'unsupported schema type'
|
129
|
+
end
|
130
|
+
i += 1
|
131
|
+
end
|
132
|
+
record
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module OdpsProtobuf
|
2
|
+
class OdpsTableRecord
|
3
|
+
attr_reader :mValues, :mSchema
|
4
|
+
|
5
|
+
def initialize(schema)
|
6
|
+
@mSchema = schema
|
7
|
+
@mValues = Array.new(@mSchema.getColumnCount)
|
8
|
+
end
|
9
|
+
|
10
|
+
def getColumnsCount
|
11
|
+
@mSchema.getColumnCount
|
12
|
+
end
|
13
|
+
|
14
|
+
def getTableSchema
|
15
|
+
@mSchema
|
16
|
+
end
|
17
|
+
|
18
|
+
def getValue(idx)
|
19
|
+
fail 'idx out of range' if idx < 0 || idx >= @mSchema.getColumnCount
|
20
|
+
@mValues.at(idx)
|
21
|
+
end
|
22
|
+
|
23
|
+
def setNullValue(idx)
|
24
|
+
setValue(idx, nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
def setBigInt(idx, value)
|
28
|
+
if value.is_a? Integer
|
29
|
+
setValue(idx, value)
|
30
|
+
elsif value.is_a? String
|
31
|
+
setValue(idx, value.to_i)
|
32
|
+
else
|
33
|
+
fail 'value show be Integer, idx:' + idx.to_s + ' value:' + value.to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def setDouble(idx, value)
|
38
|
+
if value.is_a? Float
|
39
|
+
setValue(idx, value)
|
40
|
+
elsif value.is_a? String
|
41
|
+
setValue(idx, value.to_f)
|
42
|
+
else
|
43
|
+
fail 'value show be Float, idx:' + idx.to_s + ' value:' + value.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def setBoolean(idx, value)
|
48
|
+
if value.is_a? String
|
49
|
+
if value == 'true'
|
50
|
+
setValue(idx, true)
|
51
|
+
elsif value == 'false'
|
52
|
+
setValue(idx, false)
|
53
|
+
else
|
54
|
+
fail 'value must be true or false, idx:' + idx.to_s + ' value:' + value.to_s
|
55
|
+
end
|
56
|
+
elsif value != false && value != true
|
57
|
+
fail 'value must be bool or string[true,false], idx:' + idx.to_s + ' value:' + value.to_s
|
58
|
+
end
|
59
|
+
setValue(idx, value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def setDateTime(idx, value)
|
63
|
+
if value.is_a?(Integer) && value >= $DATETIME_MIN_TICKS && value <= $DATETIME_MAX_TICKS
|
64
|
+
setValue(idx, value)
|
65
|
+
elsif value.is_a?(DateTime) || value.is_a?(Time)
|
66
|
+
if value.to_i * 1000 >= $DATETIME_MIN_TICKS && value.to_i * 1000 <= $DATETIME_MAX_TICKS
|
67
|
+
setValue(idx, value.to_i * 1000)
|
68
|
+
else
|
69
|
+
fail 'DateTime out of range or value show be Integer and between -62135798400000 and 253402271999000.'
|
70
|
+
end
|
71
|
+
elsif value.is_a? String
|
72
|
+
begin
|
73
|
+
tmpTime = Time.parse(value)
|
74
|
+
setValue(idx, tmpTime.to_i * 1000)
|
75
|
+
rescue
|
76
|
+
raise 'Parse string to datetime failed, string:' + value
|
77
|
+
end
|
78
|
+
else
|
79
|
+
fail 'DateTime cell should be in Integer or Time or DateTime format, idx:' + idx.to_s + ' value:' + value.to_s
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def setDecimal(idx, value)
|
84
|
+
if value.is_a? String
|
85
|
+
setValue(idx, value)
|
86
|
+
elsif value.is_a? Float
|
87
|
+
setValue(idx, value.to_s)
|
88
|
+
elsif value.is_a? BigDecimal
|
89
|
+
setValue(idx, value.to_s)
|
90
|
+
else
|
91
|
+
fail 'value can not be convert to decimal, idx:' + idx.to_s + ' value:' + value.to_s
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def setString(idx, value)
|
96
|
+
if value.is_a?(String) && value.length < $STRING_MAX_LENTH
|
97
|
+
setValue(idx, value)
|
98
|
+
else
|
99
|
+
fail 'value show be String and len < ' + $STRING_MAX_LENTH.to_s + ', idx:' + idx.to_s + ' value:' + value.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def setValue(idx, value)
|
106
|
+
if idx < 0 || idx >= @mSchema.getColumnCount
|
107
|
+
fail 'idx out of range, idx:' + idx.to_s + ' value:' + value.to_s
|
108
|
+
end
|
109
|
+
@mValues[idx] = value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
$ODPS_BIGINT = 'bigint'
|
114
|
+
$ODPS_DOUBLE = 'double'
|
115
|
+
$ODPS_BOOLEAN = 'boolean'
|
116
|
+
$ODPS_DATETIME = 'datetime'
|
117
|
+
$ODPS_STRING = 'string'
|
118
|
+
$ODPS_DECIMAL = 'decimal'
|
119
|
+
|
120
|
+
class OdpsTableColumn
|
121
|
+
attr_reader :mName, :mType, :mIdx
|
122
|
+
def initialize(name, type, idx)
|
123
|
+
@mName = name
|
124
|
+
@mType = type
|
125
|
+
@mIdx = idx
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class OdpsTableSchema
|
130
|
+
attr_accessor :mCols
|
131
|
+
def initialize(jsonobj = nil)
|
132
|
+
@mCols = []
|
133
|
+
unless jsonobj.nil?
|
134
|
+
columns = jsonobj['columns']
|
135
|
+
columns.each do |object|
|
136
|
+
appendColumn(object['name'], object['type'])
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def getColumnCount
|
142
|
+
@mCols.size
|
143
|
+
end
|
144
|
+
|
145
|
+
def getColumnType(idx)
|
146
|
+
fail 'idx out of range' if idx < 0 || idx >= @mCols.size
|
147
|
+
@mCols.at(idx).mType
|
148
|
+
end
|
149
|
+
|
150
|
+
def appendColumn(name, type)
|
151
|
+
col = OdpsTableColumn.new(name, type, @mCols.size)
|
152
|
+
@mCols.push(col)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: odps_protobuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Newell Zhu
|
@@ -82,6 +82,26 @@ files:
|
|
82
82
|
- bin/console
|
83
83
|
- bin/setup
|
84
84
|
- lib/odps_protobuf.rb
|
85
|
+
- lib/odps_protobuf/crc/crc.rb
|
86
|
+
- lib/odps_protobuf/crc/lib/linux/crc32c.so
|
87
|
+
- lib/odps_protobuf/crc/lib/win/crc32c.so
|
88
|
+
- lib/odps_protobuf/crc/origin/crc.rb
|
89
|
+
- lib/odps_protobuf/crc/origin/crc32.rb
|
90
|
+
- lib/odps_protobuf/crc/origin/crc32c.rb
|
91
|
+
- lib/odps_protobuf/deserializer.rb
|
92
|
+
- lib/odps_protobuf/field.rb
|
93
|
+
- lib/odps_protobuf/field/bool_field.rb
|
94
|
+
- lib/odps_protobuf/field/datetime_field.rb
|
95
|
+
- lib/odps_protobuf/field/decimal_field.rb
|
96
|
+
- lib/odps_protobuf/field/double_field.rb
|
97
|
+
- lib/odps_protobuf/field/fixed32_field.rb
|
98
|
+
- lib/odps_protobuf/field/fixed64_field.rb
|
99
|
+
- lib/odps_protobuf/field/fixed_string_field.rb
|
100
|
+
- lib/odps_protobuf/field/sint64_field.rb
|
101
|
+
- lib/odps_protobuf/field/string_field.rb
|
102
|
+
- lib/odps_protobuf/field/uint32_field.rb
|
103
|
+
- lib/odps_protobuf/serializer.rb
|
104
|
+
- lib/odps_protobuf/table.rb
|
85
105
|
- lib/odps_protobuf/version.rb
|
86
106
|
- odps_protobuf.gemspec
|
87
107
|
homepage: https://github.com/zlx.
|