monetdb 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +0,0 @@
1
- require "monetdb/core_ext/string"
@@ -1,67 +0,0 @@
1
- #
2
- # Overload the class string to convert monetdb to ruby types.
3
- #
4
-
5
- class String
6
-
7
- def getInt
8
- to_i
9
- end
10
-
11
- def getFloat
12
- to_f
13
- end
14
-
15
- def getString
16
- gsub(/^"/, "").gsub(/"$/, "")
17
- end
18
-
19
- # Convert from HEX to the origianl binary data.
20
- def getBlob
21
- blob = ""
22
- scan(/../) { |tuple| blob += tuple.hex.chr }
23
- blob
24
- end
25
-
26
- # Ruby currently supports only time formatted timestamps; treat TIME as string.
27
- def getTime
28
- gsub(/^"/, "").gsub(/"$/, "")
29
- end
30
-
31
- # Ruby currently supports only date formatted timestamps; treat DATE as string.
32
- def getDate
33
- gsub(/^"/, "").gsub(/"$/, "")
34
- end
35
-
36
- def getDateTime
37
- date = split(" ")[0].split("-")
38
- time = split(" ")[1].split(":")
39
- Time.gm(date[0], date[1], date[2], time[0], time[1], time[2])
40
- end
41
-
42
- def getChar
43
- # Ruby < 1.9 does not have a char datatype
44
- begin
45
- ord
46
- rescue
47
- self
48
- end
49
- end
50
-
51
- def getBool
52
- if %w(1 y t true).include?(self)
53
- true
54
- elsif %w(0 n f false).include?(self)
55
- false
56
- end
57
- end
58
-
59
- def getNull
60
- if upcase == "NONE"
61
- nil
62
- else
63
- raise "Unknown value"
64
- end
65
- end
66
-
67
- end
data/lib/monetdb/data.rb DELETED
@@ -1,300 +0,0 @@
1
- require "time"
2
- require "ostruct"
3
- require "bigdecimal"
4
- require "logger"
5
-
6
- #
7
- # Models a MonetDB RecordSet
8
- #
9
-
10
- class MonetDB
11
- class Data
12
-
13
- @@DEBUG = false
14
-
15
- def initialize(connection)
16
- @connection = connection
17
- @lang = @connection.lang
18
-
19
- @header = []
20
- @query = {}
21
-
22
- @record_set = []
23
- @index = 0 # Position of the last returned record
24
-
25
- @row_count = 0
26
- @row_offset = 10
27
- @row_index = Integer(REPLY_SIZE)
28
- end
29
-
30
- # Fire a query and return the server response.
31
- def execute(q)
32
- # fire a query and get ready to receive the data
33
- @connection.send(format_query(q))
34
- data = @connection.receive
35
-
36
- return if data == nil
37
-
38
- record_set = "" # temporarly store retrieved rows
39
- record_set = receive_record_set(data)
40
-
41
- if (@lang == LANG_SQL) or (@lang == LANG_XQUERY and XQUERY_OUTPUT_SEQ)
42
- rows = receive_record_set(data)
43
- # the fired query is a SELECT; store and return the whole record set
44
- if @action == Q_TABLE
45
- @header = parse_header_table(@header)
46
- @header.freeze
47
-
48
- if @row_index.to_i < @row_count.to_i
49
- block_rows = ""
50
- while next_block
51
- data = @connection.receive
52
- block_rows += receive_record_set(data)
53
- end
54
- record_set += block_rows
55
- end
56
- end
57
-
58
- # ruby string management seems to not properly understand the MSG_PROMPT escape character.
59
- # In order to avoid data loss the @record_set array is built once that all tuples have been retrieved
60
- @record_set = record_set.split("\t]\n")
61
-
62
- if @record_set.length != @query['rows'].to_i
63
- raise MonetDB::QueryError, "Warning: Query #{@query['id']} declared to result in #{@query['rows']} but #{@record_set.length} returned instead"
64
- end
65
- elsif (@lang == XQUERY and ! XQUERY_OUTPUT_SEQ)
66
- return data # return an xml file
67
- end
68
- @record_set.freeze
69
- end
70
-
71
- # Free memory used to store the record set.
72
- def free
73
- @connection = nil
74
-
75
- @header = []
76
- @query = {}
77
-
78
- @record_set = []
79
- @index = 0 # Position of the last returned record
80
-
81
- @row_index = Integer(REPLY_SIZE)
82
- @row_count = 0
83
- @row_offset = 10
84
- end
85
-
86
- # Returns the record set entries hashed by column name orderd by column position.
87
- def fetch_all_hash
88
- columns = {}
89
- @header["columns_name"].each do |col_name|
90
- columns[col_name] = fetch_column_name(col_name)
91
- end
92
- columns
93
- end
94
-
95
- def fetch_hash
96
- if @index >= @query["rows"].to_i
97
- false
98
- else
99
- columns = {}
100
- @header["columns_name"].each do |col_name|
101
- position = @header["columns_order"].fetch(col_name)
102
- row = parse_tuple(@record_set[@index])
103
- columns[col_name] = row[position]
104
- end
105
- @index += 1
106
- columns
107
- end
108
- end
109
-
110
- # Returns the values for the column 'field'.
111
- def fetch_column_name(field = "")
112
- position = @header["columns_order"].fetch(field)
113
- col = Array.new
114
- @record_set.each do |row|
115
- col << parse_tuple(row[position])
116
- end
117
- col
118
- end
119
-
120
- def fetch
121
- @index
122
- if @index > @query["rows"].to_i
123
- false
124
- else
125
- parse_tuple(@record_set[@index])
126
- @index += 1
127
- end
128
- end
129
-
130
- # Cursor method that retrieves all the records present in a table and stores them in a cache.
131
- def fetch_all
132
- if @query['type'] == Q_TABLE
133
- rows = Array.new
134
- @record_set.each do |row|
135
- rows << parse_tuple(row)
136
- end
137
- @index = Integer(rows.length)
138
- else
139
- raise MonetDB::DataError, "There is no record set currently available"
140
- end
141
- rows
142
- end
143
-
144
- # Returns the number of rows in the record set.
145
- def num_rows()
146
- @query["rows"].to_i
147
- end
148
-
149
- # Returns the number of fields in the record set.
150
- def num_fields()
151
- @query["columns"].to_i
152
- end
153
-
154
- # Returns the (ordered) name of the columns in the record set.
155
- def name_fields()
156
- @header["columns_name"]
157
- end
158
-
159
- # Returns the (ordered) name of the columns in the record set.
160
- def type_fields
161
- @header["columns_type"]
162
- end
163
-
164
- private
165
-
166
- # Store block of data, parse it and store it.
167
- def receive_record_set(response)
168
- rows = ""
169
- response.each_line do |row|
170
- if row[0].chr == MSG_QUERY
171
- if row[1].chr == Q_TABLE
172
- @action = Q_TABLE
173
- @query = parse_header_query(row)
174
- @query.freeze
175
- @row_count = @query['rows'].to_i #total number of rows in table
176
- elsif row[1].chr == Q_BLOCK
177
- # strip the block header from data
178
- @action = Q_BLOCK
179
- @block = parse_header_query(row)
180
- elsif row[1].chr == Q_TRANSACTION
181
- @action = Q_TRANSACTION
182
- elsif row[1].chr == Q_CREATE
183
- @action = Q_CREATE
184
- end
185
- elsif row[0].chr == MSG_INFO
186
- raise MonetDB::QueryError, row
187
- elsif row[0].chr == MSG_SCHEMA_HEADER
188
- # process header data
189
- @header << row
190
- elsif row[0].chr == MSG_TUPLE
191
- rows += row
192
- elsif row[0] == MSG_PROMPT
193
- return rows
194
- end
195
- end
196
- rows # return an array of unparsed tuples
197
- end
198
-
199
- def next_block
200
- if @row_index == @row_count
201
- return false
202
- else
203
- # The increment step is small to better deal with ruby socket's performance.
204
- # For larger values of the step performance drop;
205
- #
206
- @row_offset = [@row_offset, (@row_count - @row_index)].min
207
-
208
- # export offset amount
209
- @connection.set_export(@query['id'], @row_index.to_s, @row_offset.to_s)
210
- @row_index += @row_offset
211
- @row_offset += 1
212
- end
213
- true
214
- end
215
-
216
- # Formats a query <i>string</i> so that it can be parsed by the server.
217
- def format_query(q)
218
- if @lang.downcase == LANG_SQL
219
- "s" + q + ";"
220
- elsif @lang.downcase == LANG_XQUERY
221
- "s" + q
222
- else
223
- raise LanguageNotSupported, @lang
224
- end
225
- end
226
-
227
- # Parse one tuple as returned from the server.
228
- def parse_tuple(tuple)
229
- fields = Array.new
230
- # remove trailing "["
231
- tuple = tuple.gsub(/^\[\s+/,'')
232
-
233
- tuple.split(/,\t/).each do |f|
234
- fields << f.gsub(/\\/, '').gsub(/^"/,'').gsub(/"$/,'').gsub(/\"/, '')
235
- end
236
-
237
- return fields.freeze
238
- end
239
-
240
- # Parses a query header and returns information about the query.
241
- def parse_header_query(row)
242
- type = row[1].chr
243
- if type == Q_TABLE
244
- # Performing a SELECT: store informations about the table size, query id, total number of records and returned.
245
- id = row.split(' ')[1]
246
- rows = row.split(' ')[2]
247
- columns = row.split(' ')[3]
248
- returned = row.split(' ')[4]
249
-
250
- header = { "id" => id, "type" => type, "rows" => rows, "columns" => columns, "returned" => returned }
251
- elsif type == Q_BLOCK
252
- # processing block header
253
-
254
- id = row.split(' ')[1]
255
- columns = row.split(' ')[2]
256
- remains = row.split(' ')[3]
257
- offset = row.split(' ')[4]
258
-
259
- header = { "id" => id, "type" => type, "remains" => remains, "columns" => columns, "offset" => offset }
260
- else
261
- header = {"type" => type}
262
- end
263
- header.freeze
264
- end
265
-
266
- # Parses a Q_TABLE header and returns information about the schema.
267
- def parse_header_table(header_t)
268
- if @query["type"] == Q_TABLE
269
- if header_t != nil
270
- name_t = header_t[0].split(' ')[1].gsub(/,$/, '')
271
- name_cols = Array.new
272
-
273
- header_t[1].split('%')[1].gsub(/'^\%'/, '').split('#')[0].split(' ').each do |col|
274
- name_cols << col.gsub(/,$/, '')
275
- end
276
-
277
- type_cols = { }
278
- header_t[2].split('%')[1].gsub(/'^\%'/, '').split('#')[0].split(' ').each_with_index do |col, i|
279
- if col.gsub(/,$/, '') != nil
280
- type_cols[ name_cols[i] ] = col.gsub(/,$/, '')
281
- end
282
- end
283
-
284
- length_cols = { }
285
- header_t[3].split('%')[1].gsub(/'^\%'/, '').split('#')[0].split(' ').each_with_index do |col, i|
286
- length_cols[ name_cols[i] ] = col.gsub(/,$/, '')
287
- end
288
-
289
- columns_order = {}
290
- name_cols.each_with_index do |col, i|
291
- columns_order[col] = i
292
- end
293
-
294
- {"table_name" => name_t, "columns_name" => name_cols, "columns_type" => type_cols, "columns_length" => length_cols, "columns_order" => columns_order}.freeze
295
- end
296
- end
297
- end
298
- end
299
-
300
- end
@@ -1,40 +0,0 @@
1
- require "digest/md5"
2
- require "digest/sha1"
3
- require "digest/sha2"
4
-
5
- class MonetDB
6
- class Hasher
7
-
8
- def initialize(method, pwd)
9
- case method.upcase
10
- when "SHA1"
11
- @hashfunc = Digest::SHA1.new
12
- @hashname = method.upcase
13
- when "SHA256"
14
- @hashfunc = Digest::SHA256.new
15
- @hashname = method.upcase
16
- when "SHA384"
17
- @hashfunc = Digest::SHA384.new
18
- @hashname = method.upcase
19
- when "SHA512"
20
- @hashfunc = Digest::SHA512.new
21
- @hashname = method.upcase
22
- else
23
- @hashfunc = Digest::MD5.new
24
- @hashname = "MD5"
25
- end
26
- @pwd = pwd
27
- end
28
-
29
- # Returns the hash method
30
- def hashname
31
- @hashname
32
- end
33
-
34
- # Compute hash code
35
- def hashsum
36
- @hashfunc.hexdigest(@pwd)
37
- end
38
-
39
- end
40
- end
@@ -1,36 +0,0 @@
1
- #
2
- # Handles transactions and savepoints. Can be used to simulate nested transactions.
3
- #
4
-
5
- class MonetDB
6
- class Transaction
7
-
8
- def initialize
9
- @id = 0
10
- @savepoint = ""
11
- end
12
-
13
- def savepoint
14
- @savepoint = "monetdbsp#{@id}"
15
- end
16
-
17
- def release
18
- prev_id
19
- end
20
-
21
- def save
22
- next_id
23
- end
24
-
25
- private
26
-
27
- def next_id
28
- @id += 1
29
- end
30
-
31
- def prev_id
32
- @id -= 1
33
- end
34
-
35
- end
36
- end