azure-storage-table 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,133 @@
1
+ #-------------------------------------------------------------------------
2
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
3
+ #
4
+ # The MIT License(MIT)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files(the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions :
12
+
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #--------------------------------------------------------------------------
24
+ module Azure::Storage
25
+ module Table
26
+ module BatchResponse
27
+ def self.parse(data, is_get)
28
+ context = {
29
+ lines: data.lines.to_a,
30
+ index: 0,
31
+ responses: []
32
+ }
33
+
34
+ find(context) { |c| batch_boundary c }
35
+ find(context) { |c| batch_headers c }
36
+
37
+ if is_get
38
+ find(context) { |c| response c }
39
+ find(context) { |c| response_headers c }
40
+ find(context) { |c| response_body c }
41
+ else
42
+ while (find(context) { |c| changeset_boundary_or_end c } == :boundary)
43
+ find(context) { |c| changeset_headers c }
44
+ find(context) { |c| response c }
45
+ find(context) { |c| response_headers c }
46
+ find(context) { |c| response_body c }
47
+ end
48
+ end
49
+
50
+ context[:responses]
51
+ end
52
+
53
+ def self.find(context, &block)
54
+ while (context[:index] < context[:lines].length)
55
+ result = block.call(context)
56
+ return result if result
57
+ context[:index] += 1
58
+ end
59
+ end
60
+
61
+ def self.response_body(context)
62
+ end_of_body = nil
63
+ end_of_body = changeset_boundary_or_end(context.dup.merge!(index: context[:index] + 1)) if context[:index] < (context[:lines].length - 1)
64
+
65
+ if end_of_body
66
+ context[:responses].last[:body] ||= ""
67
+ context[:responses].last[:body] << current_line(context)
68
+ return context[:responses].last[:body]
69
+ else
70
+ context[:responses].last[:body] ||= ""
71
+ context[:responses].last[:body] << current_line(context)
72
+ return nil
73
+ end
74
+ end
75
+
76
+ def self.response_headers(context)
77
+ match = /(.*): (.*)/.match(current_line(context))
78
+
79
+ if context[:responses].last[:headers] && (not match)
80
+ context[:index] += 1
81
+ return context[:responses].last[:headers]
82
+ elsif match
83
+ context[:responses].last[:headers] ||= {}
84
+ context[:responses].last[:headers][match[1].downcase] = match[2].strip
85
+ return nil
86
+ else
87
+ return nil
88
+ end
89
+ end
90
+
91
+ def self.response(context)
92
+ match = /HTTP\/1.1 (\d*) (.*)/.match(current_line(context))
93
+ return nil unless match
94
+ response = { status_code: match[1], message: match[2] }
95
+ context[:responses].push response
96
+ end
97
+
98
+ def self.changeset_headers(context)
99
+ current_line(context).strip == ""
100
+ end
101
+
102
+ def self.changeset_boundary_or_end(context)
103
+ match_boundary = /--changesetresponse_(.*)/.match(current_line(context))
104
+ match_end = /--changesetresponse_(.*)--/.match(current_line(context)) || /--batchresponse_(.*)--/.match(current_line(context))
105
+
106
+ (match_boundary && (not match_end)) ? :boundary : (match_end ? :end : nil)
107
+ end
108
+
109
+ def self.batch_headers(context)
110
+ match = /(.*): (.*)/.match(current_line(context))
111
+
112
+ if context[:batch_headers] && (not match)
113
+ return context[:batch_headers]
114
+ elsif match
115
+ context[:batch_headers] ||= {}
116
+ context[:batch_headers][match[1].downcase] = match[2]
117
+ return nil
118
+ else
119
+ return nil
120
+ end
121
+ end
122
+
123
+ def self.batch_boundary(context)
124
+ match = /--batchresponse_(.*)/.match(current_line(context))
125
+ match ? match[1] : nil
126
+ end
127
+
128
+ def self.current_line(context)
129
+ context[:lines][context[:index]]
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+
27
+ require "rbconfig"
28
+ require "azure/storage/table/version"
29
+
30
+ module Azure::Storage::Table
31
+ module Default
32
+ # Default REST service (STG) version number
33
+ STG_VERSION = "2016-05-31"
34
+
35
+ # The number of default concurrent requests for parallel operation.
36
+ DEFAULT_PARALLEL_OPERATION_THREAD_COUNT = 1
37
+
38
+ # Constant representing a kilobyte (Non-SI version).
39
+ KB = 1024
40
+ # Constant representing a megabyte (Non-SI version).
41
+ MB = 1024 * 1024
42
+ # Constant representing a gigabyte (Non-SI version).
43
+ GB = 1024 * 1024 * 1024
44
+
45
+ # Specifies HTTP.
46
+ HTTP = "http"
47
+ # Specifies HTTPS.
48
+ HTTPS = "https"
49
+ # Default HTTP port.
50
+ DEFAULT_HTTP_PORT = 80
51
+ # Default HTTPS port.
52
+ DEFAULT_HTTPS_PORT = 443
53
+
54
+ # Marker for atom metadata.
55
+ XML_METADATA_MARKER = "$"
56
+ # Marker for atom value.
57
+ XML_VALUE_MARKER = "_"
58
+
59
+ # Default User Agent header string
60
+ USER_AGENT = "Azure-Storage/#{Azure::Storage::Table::Version.to_uas}-#{Azure::Storage::Common::Version.to_uas} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}; #{Azure::Storage::Common::Default.os})".freeze
61
+ end
62
+
63
+ # Defines constants for use with table storage.
64
+ module TableConstants
65
+ # The changeset response delimiter.
66
+ CHANGESET_DELIMITER = "--changesetresponse_"
67
+
68
+ # The batch response delimiter.
69
+ BATCH_DELIMITER = "--batchresponse_"
70
+
71
+ # The next continuation row key token.
72
+ CONTINUATION_NEXT_ROW_KEY = "x-ms-continuation-nextrowkey"
73
+
74
+ # The next continuation partition key token.
75
+ CONTINUATION_NEXT_PARTITION_KEY = "x-ms-continuation-nextpartitionkey"
76
+
77
+ # The next continuation table name token.
78
+ CONTINUATION_NEXT_TABLE_NAME = "x-ms-continuation-nexttablename"
79
+
80
+ # The next row key query string argument.
81
+ NEXT_ROW_KEY = "NextRowKey"
82
+
83
+ # The next partition key query string argument.
84
+ NEXT_PARTITION_KEY = "NextPartitionKey"
85
+
86
+ # The next table name query string argument.
87
+ NEXT_TABLE_NAME = "NextTableName"
88
+
89
+ # Prefix of the odata properties returned in a JSON query
90
+ ODATA_PREFIX = "odata."
91
+
92
+ # Constant representing the string following a type annotation in a JSON table query
93
+ ODATA_TYPE_SUFFIX = "@odata.type"
94
+
95
+ # Constant representing the property where the odata metadata elements are stored.
96
+ ODATA_METADATA_MARKER = ".metadata"
97
+
98
+ # Constant representing the value for an entity property.
99
+ ODATA_VALUE_MARKER = "_"
100
+
101
+ # Constant representing the type for an entity property.
102
+ ODATA_TYPE_MARKER = "$"
103
+
104
+ # Constant representing the hash key of etag for an entity property in JSON.
105
+ ODATA_ETAG = "odata.etag"
106
+
107
+ # The value to set the maximum data service version header.
108
+ DEFAULT_DATA_SERVICE_VERSION = "3.0;NetFx"
109
+
110
+ # The name of the property that stores the table name.
111
+ TABLE_NAME = "TableName"
112
+
113
+ # The name of the special table used to store tables.
114
+ TABLE_SERVICE_TABLE_NAME = "Tables"
115
+
116
+ # The key of partition key in hash
117
+ PARTITION_KEY = "PartitionKey"
118
+
119
+ # The key of row key in hash
120
+ ROW_KEY = "RowKey"
121
+
122
+ # Operations
123
+ module Operations
124
+ RETRIEVE = "RETRIEVE"
125
+ INSERT = "INSERT"
126
+ UPDATE = "UPDATE"
127
+ MERGE = "MERGE"
128
+ DELETE = "DELETE"
129
+ INSERT_OR_REPLACE = "INSERT_OR_REPLACE"
130
+ INSERT_OR_MERGE = "INSERT_OR_MERGE"
131
+ end
132
+ end
133
+
134
+ module TableErrorCodeStrings
135
+ XMETHOD_NOT_USING_POST = "XMethodNotUsingPost"
136
+ XMETHOD_INCORRECT_VALUE = "XMethodIncorrectValue"
137
+ XMETHOD_INCORRECT_COUNT = "XMethodIncorrectCount"
138
+ TABLE_HAS_NO_PROPERTIES = "TableHasNoProperties"
139
+ DUPLICATE_PROPERTIES_SPECIFIED = "DuplicatePropertiesSpecified"
140
+ TABLE_HAS_NO_SUCH_PROPERTY = "TableHasNoSuchProperty"
141
+ DUPLICATE_KEY_PROPERTY_SPECIFIED = "DuplicateKeyPropertySpecified"
142
+ TABLE_ALREADY_EXISTS = "TableAlreadyExists"
143
+ TABLE_NOT_FOUND = "TableNotFound"
144
+ ENTITY_NOT_FOUND = "EntityNotFound"
145
+ ENTITY_ALREADY_EXISTS = "EntityAlreadyExists"
146
+ PARTITION_KEY_NOT_SPECIFIED = "PartitionKeyNotSpecified"
147
+ OPERATOR_INVALID = "OperatorInvalid"
148
+ UPDATE_CONDITION_NOT_SATISFIED = "UpdateConditionNotSatisfied"
149
+ PROPERTIES_NEED_VALUE = "PropertiesNeedValue"
150
+ PARTITION_KEY_PROPERTY_CANNOT_BE_UPDATED = "PartitionKeyPropertyCannotBeUpdated"
151
+ TOO_MANY_PROPERTIES = "TooManyProperties"
152
+ ENTITY_TOO_LARGE = "EntityTooLarge"
153
+ PROPERTY_VALUE_TOO_LARGE = "PropertyValueTooLarge"
154
+ INVALID_VALUE_TYPE = "InvalidValueType"
155
+ TABLE_BEING_DELETED = "TableBeingDeleted"
156
+ TABLE_SERVER_OUT_OF_MEMORY = "TableServerOutOfMemory"
157
+ PRIMARY_KEY_PROPERTY_IS_INVALID_TYPE = "PrimaryKeyPropertyIsInvalidType"
158
+ PROPERTY_NAME_TOO_LONG = "PropertyNameTooLong"
159
+ PROPERTY_NAME_INVALID = "PropertyNameInvalid"
160
+ BATCH_OPERATION_NOT_SUPPORTED = "BatchOperationNotSupported"
161
+ JSON_FORMAT_NOT_SUPPORTED = "JsonFormatNotSupported"
162
+ METHOD_NOT_ALLOWED = "MethodNotAllowed"
163
+ NOT_IMPLEMENTED = "NotImplemented"
164
+ end
165
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "time"
27
+ require "date"
28
+
29
+ module Azure::Storage
30
+ module Table
31
+ module EdmType
32
+ # Public: Get the Edm type of an object
33
+ #
34
+ # value - Object. An typed instance
35
+ #
36
+ # Returns the Edm type as a String
37
+ def self.property_type(value)
38
+ case value
39
+ when Float
40
+ "Edm.Double"
41
+ when Date, Time, DateTime
42
+ "Edm.DateTime"
43
+ when Integer
44
+ value.abs < 2**31 ? "Edm.Int32" : "Edm.Int64"
45
+ when TrueClass, FalseClass
46
+ "Edm.Boolean"
47
+ when GUID
48
+ "Edm.Guid"
49
+ when IO, File
50
+ "Edm.Binary"
51
+ when String
52
+ value.encoding.names.include?("BINARY") ? "Edm.Binary" : ""
53
+ else
54
+ value.kind_of?(IO) ? "Edm.Binary" : ""
55
+ end
56
+ end
57
+
58
+ # Public: Get the value of a property in a serialized way
59
+ #
60
+ # value - Object. An typed instance
61
+ #
62
+ # Returns the Edm type as a String
63
+ def self.serialize_value(type, value)
64
+ case type
65
+ when "Edm.Double", "Edm.Int32", "Edm.Int64", "Edm.Guid", "Edm.String", nil
66
+ value.to_s
67
+ when "Edm.Binary"
68
+ Base64.encode64(value.to_s).chomp("\n")
69
+ when "Edm.DateTime"
70
+ to_edm_time(value)
71
+ else
72
+ value.to_s
73
+ end
74
+ end
75
+
76
+ # Public: Serializes EDM value into proper value to be used in query.
77
+ #
78
+ # value - String. The value to serialize.
79
+ #
80
+ # Returns the serialized value
81
+ def self.serialize_query_value(value)
82
+ case value
83
+ when Date, Time, DateTime
84
+ "datetime'#{value.iso8601}'"
85
+ when TrueClass, FalseClass
86
+ value ? "true" : "false"
87
+ when Float, Integer
88
+ value.abs < 2**31 ? value.to_s : value.to_s + "L"
89
+ when GUID
90
+ "guid'#{value.to_s}'"
91
+ when IO, File
92
+ "X'" + value.to_s.unpack("H*").join("") + "'"
93
+ else
94
+ if value != nil && value.encoding.names.include?("BINARY")
95
+ "X'" + value.to_s.unpack("H*").join("") + "'"
96
+ else
97
+ # NULL also is treated as EdmType::STRING
98
+ value.to_s.gsub("'", "''");
99
+ end
100
+ end
101
+ end
102
+
103
+ # Public: Convert a serialized value into an typed object
104
+ #
105
+ # value - String. The Edm value
106
+ # type - String. The Edm datatype
107
+ #
108
+ # Returns an typed object
109
+ def self.deserialize_value(value, type)
110
+ case type
111
+ when "Edm.DateTime"
112
+ Time.parse(value)
113
+ when "Edm.Double"
114
+ Float(value)
115
+ when "Edm.Int32", "Edm.Int64"
116
+ Integer(value)
117
+ when "Edm.Boolean"
118
+ value == true || value == "true" ? true : false
119
+ when "Edm.Guid"
120
+ GUID.new(value.to_s)
121
+ when "Edm.Binary"
122
+ Base64.decode64(value.to_s).force_encoding("BINARY")
123
+ else
124
+ value == "" ? nil : value.to_s
125
+ end
126
+ end
127
+
128
+ def self.to_edm_time(value)
129
+ date = value.is_a?(Time) ? value : Time.parse(value)
130
+ date.utc.strftime("%Y-%m-%dT%H:%M:%S.%6N0Z")
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+
27
+ module Azure::Storage
28
+ module Table
29
+ class Entity
30
+ def initialize
31
+ @properties = {}
32
+ yield self if block_given?
33
+ end
34
+
35
+ attr_accessor :etag
36
+ attr_accessor :properties
37
+ end
38
+ end
39
+ end