odps_protobuf 0.1.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|