monetdb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MDVhN2NmYTg2YWQwZTA5M2ExNTg5NzVhZGMxNWY1YjBlY2U4YjcxOQ==
5
+ data.tar.gz: !binary |-
6
+ ZDdmNWE5YWI2NWI0ZjM4NGI1YWU0YTM3M2NkNjdmMzk2N2U3MjQyNg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ M2JjNTcwY2JjOWViMTM2YTVmOTFlZGQ0MWY0NDVlZDNiNjg3NGMyZmMzNmQ2
10
+ OGJhMjdjN2RlM2FiY2UyNzhjYjc5NDQ0NWRiMzdmMWM1M2VhZjAwNGM0M2Fh
11
+ OGY2NWVkYWMwYTc5MWRhYWZjYmI3Y2Y0MDFlOTAyY2UwY2UzYmU=
12
+ data.tar.gz: !binary |-
13
+ ZjNhMzJjMjUzODZiN2M4N2M1OWYyNjJjMzdjNmU3YzQzZWYyMGUyNjJkZmZk
14
+ N2Q2NmJiNWU3MDA0YmNhMzg4MjJjMDRkZGExZDhkOWFkYzU2MDhhNzZjZTVl
15
+ ZDk0MmZmODE5MTUwMmQwYjQxMDI0ZGZiZDM3YzZhNGJhYWFlNmQ=
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+ .bundle
3
+ .yardoc
4
+ .rvmrc
5
+ Gemfile.lock
6
+ doc
7
+ pkg
8
+ test/coverage
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,5 @@
1
+ = MonetDB CHANGELOG
2
+
3
+ == Version 0.1.0 (August 28, 2014)
4
+
5
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "yard"
7
+ end
8
+
9
+ group :development, :test do
10
+ gem "monetdb", :path => "."
11
+ gem "pry"
12
+ end
13
+
14
+ group :test do
15
+ gem "simplecov", :require => false
16
+ gem "minitest"
17
+ gem "mocha"
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ monetdb (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.1.0)
10
+ docile (1.1.5)
11
+ metaclass (0.0.4)
12
+ method_source (0.8.2)
13
+ minitest (5.4.0)
14
+ mocha (1.1.0)
15
+ metaclass (~> 0.0.1)
16
+ multi_json (1.10.1)
17
+ pry (0.10.0)
18
+ coderay (~> 1.1.0)
19
+ method_source (~> 0.8.1)
20
+ slop (~> 3.4)
21
+ rake (10.3.2)
22
+ simplecov (0.9.0)
23
+ docile (~> 1.1.0)
24
+ multi_json
25
+ simplecov-html (~> 0.8.0)
26
+ simplecov-html (0.8.0)
27
+ slop (3.6.0)
28
+ yard (0.8.7.4)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ minitest
35
+ mocha
36
+ monetdb!
37
+ pry
38
+ rake
39
+ simplecov
40
+ yard
data/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ The contents of this repository are subject to the MonetDB Public License
2
+ Version 1.1 (the "License"); you may not use this file except in
3
+ compliance with the License. You may obtain a copy of the License at
4
+ https://www.monetdb.org/Legal/MonetDBLicense
5
+
6
+ Software distributed under the License is distributed on an "AS IS"
7
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
8
+ License for the specific language governing rights and limitations
9
+ under the License.
10
+
11
+ The Original Code is the MonetDB Database System.
12
+
13
+ The Initial Developer of the Original Code is CWI.
14
+ Portions created by CWI are Copyright (C) 1997-July 2008 CWI.
15
+
16
+ Copyright August 2008-2011 MonetDB B.V.
17
+ All Rights Reserved.
data/README.rdoc ADDED
@@ -0,0 +1,154 @@
1
+ == Standalone driver ==
2
+ This directory contains the a ruby interface to monetdb5
3
+ written in pure ruby.
4
+
5
+ lib/MonetDB.rb
6
+ lib/MonetDBConnection.rb
7
+ lib/MonetDBStatements.rb
8
+ lib/MonetDBData.rb
9
+ lib/MonetDBExceptions.rb
10
+ lib/hasher.rb
11
+ lib/demo.rb: demo application how to interact with the database
12
+
13
+ ruby-monetdb-sql-0.1.gemspec: make file for rubygems
14
+
15
+ doc/: rubydoc in HTML format
16
+
17
+ == Installation ==
18
+
19
+ The standalone monetdb driver can be installed using the RubyGems Package Manager.
20
+
21
+ First build a gem file starting from the gemspec configuration:
22
+
23
+ $ gem build ruby-monetdb-sql-0.1.gemspec
24
+
25
+ Then install with the command:
26
+
27
+ $ gem install ruby-monetdb-sql-0.1.gem
28
+
29
+ == Usage ==
30
+ To use the standalone driver import the 'MonetDB' class and 'rubygems' (in case you installed it using gems).
31
+
32
+ A typical sequence of events is as follows:
33
+ Invoke query using the database handle to send the statement to the server and get back a result set object.
34
+
35
+ A result set object has methods for fetching rows, moving around in the result set, obtaining column metadata, and releasing the result set.
36
+ Use a row fetching method such as fetch_row or an iterator such as each to access the rows of the result set.
37
+ If you want a count of the number of rows in the result set: invoke 'num_rows' method.
38
+ Invoke 'free' to release the result set.
39
+
40
+ == Example ==
41
+
42
+ require 'MonetDB'
43
+
44
+ db = MonetDB.new
45
+ db.connect(user = "monetdb", passwd = "monetdb", lang = "sql", host="127.0.0.1", port = 50000, db_name = "demo", auth_type = "SHA1")
46
+
47
+ # set type_cast=true to enable MonetDB to Ruby type mapping
48
+ res = db.query("SELECT * from tables;", type_cast = false)
49
+
50
+ #puts res.debug_columns_type
51
+
52
+ puts "Number of rows returned: " + res.num_rows.to_s
53
+ puts "Number of fields: " + res.num_fields.to_s
54
+
55
+
56
+ # Get the columns' name
57
+ col_names = res.name_fields
58
+
59
+
60
+ # Iterate over the record set and retrieve on row at a time
61
+ puts res.fetch
62
+ while row = res.fetch do
63
+ printf "%s \n", row
64
+ end
65
+
66
+ # Release the result set.
67
+ res.free
68
+
69
+ # Disconnect from server
70
+ db.close
71
+
72
+ See lib/demo.rb and the MonetDBDatar class documentation for more examples.
73
+
74
+
75
+
76
+ == ActiveRecord connector adapter ==
77
+ Active Record connects business objects and database tables to create a persistable domain model where logic and data are presented in one wrapping. It‘s an implementation of the object-relational mapping (ORM) pattern.
78
+
79
+ Required files:
80
+
81
+ adapter/lib/active_record/monetdb_adapter.rb
82
+
83
+ Usage example follows:
84
+ require 'active_record'
85
+
86
+ ActiveRecord::Base.logger = Logger.new(STDERR)
87
+ ActiveRecord::Base.colorize_logging = true
88
+
89
+ ActiveRecord::Base.establish_connection(
90
+ :adapter => "monetdb",
91
+ :host => "localhost",
92
+ :database => "demo"
93
+ )
94
+
95
+ # Create a new table
96
+ class AddTests < ActiveRecord::Migration
97
+ def self.up
98
+ create_table :tests do |table|
99
+ table.column :name, :string
100
+ table.column :surname, :string
101
+ end
102
+ end
103
+
104
+ def self.down
105
+ drop_table :tests
106
+ end
107
+
108
+ end
109
+
110
+ AddTests.up
111
+
112
+ # Migration: add a column name with a default value
113
+ class AddAge < ActiveRecord::Migration
114
+ def self.up
115
+ add_column :tests, :age, :smallint, :default => 18
116
+ end
117
+
118
+ def self.down
119
+ remove_column :tests, :age
120
+ end
121
+
122
+ end
123
+
124
+ class Test < ActiveRecord::Base
125
+ end
126
+
127
+ # Insert an entry in the table
128
+ Test.create(:name => 'X', :surname => 'Y')
129
+
130
+ # add a column
131
+ AddAge.up
132
+
133
+ # return the first result of the query SELECT * from tables
134
+ row = Test.find(:first)
135
+ printf "SELECT * from tests LIMIT 1:\n"
136
+ printf "Name: %s, Surname: %s, Age: %s\n", row.name, row.surname, row.age
137
+
138
+ # Drop the table
139
+ AddTests.down
140
+
141
+ == Rubygem ==
142
+
143
+ The standalone ruby driver can be distributed as a ruby gem.
144
+ A gem file is already available; however, it can be generated
145
+ starting from the ruby-monetdb-sql-0.1.gemspec file:
146
+
147
+ $ gem build ruby-monetdb-sql-0.1.gemspec
148
+
149
+ To install the file run the command:
150
+
151
+ $ gem install ruby-monetdb-sql-0.1.gem
152
+
153
+ Documentation in ri and html format will be generated and installed as well
154
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ task :default => :test
7
+
8
+ Rake::TestTask.new do |test|
9
+ test.pattern = "test/**/test_*.rb"
10
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/monetdb.rb ADDED
@@ -0,0 +1,263 @@
1
+ require "monetdb/core_ext"
2
+ require "monetdb/hasher"
3
+ require "monetdb/connection"
4
+ require "monetdb/transaction"
5
+ require "monetdb/data"
6
+ require "monetdb/error"
7
+ require "monetdb/version"
8
+
9
+ # A typical sequence of events is as follows: Create a database instance (handle), invoke query using the database handle to send the statement to the server and get back a result set object.
10
+ #
11
+ # A result set object is an instance of the MonetDB::Data class and has methods for fetching rows, moving around in the result set, obtaining column metadata, and releasing the result set.
12
+ #
13
+ # Records can be returned as arrays and iterators over the set.
14
+ #
15
+ # A database handler (dbh) is an instance of the MonetDB class.
16
+ #
17
+ #
18
+ # = Connection management
19
+ #
20
+ # connect - establish a new connection
21
+ # * user : username (default is monetdb)
22
+ # * passwd : password (default is monetdb)
23
+ # * lang : language (default is sql)
24
+ # * host : server hostanme or ip (default is localhost)
25
+ # * port : server port (default is 50000)
26
+ # * db_name : name of the database to connect to
27
+ # * auth_type : hashing function to use during authentication (default is SHA1)
28
+ # connected? - returns true if there is an active connection to a server, false otherwise
29
+ # reconnect - reconnect to a server
30
+ # close - terminate a connection
31
+ # auto_commit? - returns ture if the session is running in auto commit mode, false otherwise
32
+ # auto_commit - enable/disable auto commit mode
33
+ # query - fire a query
34
+ #
35
+ # Currently MAPI protocols 8 and 9 are supported.
36
+ #
37
+ #
38
+ # = Managing record sets
39
+ #
40
+ # A record set is represented as an instance of the MonetDB::Data class; the class provides methods to manage retrieved data.
41
+ #
42
+ # The following methods allow to iterate over data:
43
+ #
44
+ # fetch - iterates over the record set and retrieves on row at a time. Each row is returned as an array
45
+ # fetch_hash - iterates over columns (on cell at a time)
46
+ # fetch_all_hash - returns record set entries hashed by column name orderd by column position
47
+ #
48
+ # To return the record set as an array (with each tuple stored as array of fields) the following method can be used:
49
+ #
50
+ # fetch_all - fetch all rows and store them
51
+ #
52
+ # Information about the retrieved record set can be obtained via the following methods:
53
+ #
54
+ # num_rows - returns the number of rows present in the record set
55
+ # num_fields - returns the number of fields (columns) that compose the schema
56
+ # name_fields - returns the (ordered) name of the schema's columns
57
+ # type_fields - returns the (ordered) types list of the schema's columns
58
+ #
59
+ # To release a record set MonetDB::Data#free can be used.
60
+ #
61
+ #
62
+ # = Type conversion
63
+ #
64
+ # A mapping between SQL and ruby type is supported. Each retrieved field can be converted to a ruby datatype via
65
+ # a getTYPE method.
66
+ #
67
+ # The currently supported cast methods are:
68
+ #
69
+ # getInt - convert to an integer value
70
+ # getFloat - convert to a floating point value
71
+ # getString - return a string representation of the value, with trailing and leading " characters removed
72
+ # getBlob - convert an SQL stored HEX string to its binary representation
73
+ # getTime - return a string representation of a TIME field
74
+ # getDate - return a string representation of a DATE field
75
+ # getDateTime - convert a TIMESTAMP field to a ruby Time object
76
+ # getChar - on Ruby >= 1.9, convert a CHAR field to char
77
+ # getBool - convert a BOOLEAN field to a ruby bool object. If the value of the field is unknown, nil is returned
78
+ # getNull - convert a NULL value to a nil object
79
+ #
80
+ #
81
+ # = Transactions
82
+ #
83
+ # By default MonetDB works in auto_commit mode. To turn this feature off MonetDB#auto_commit(flag = false) can be used.
84
+ #
85
+ # Once auto_commit has been disabled it is possible to start transactions, create/delete savepoints, rollback and commit with
86
+ # the usual SQL statements.
87
+ #
88
+ # Savepoints IDs can be generated using the MonetDB#save method. To release a savepoint ID use MonetDB#release.
89
+ #
90
+ # You can access savepoints (as a stack) with the MonetDB#transactions method.
91
+ #
92
+
93
+ class MonetDB
94
+
95
+ Q_TABLE = "1" # SELECT operation
96
+ Q_UPDATE = "2" # INSERT/UPDATE operations
97
+ Q_CREATE = "3" # CREATE/DROP TABLE operations
98
+ Q_TRANSACTION = "4" # TRANSACTION
99
+ Q_PREPARE = "5" # QPREPARE message
100
+ Q_BLOCK = "6" # QBLOCK message
101
+
102
+ MSG_REDIRECT = "^" # auth redirection through merovingian
103
+ MSG_QUERY = "&"
104
+ MSG_SCHEMA_HEADER = "%"
105
+ MSG_INFO = "!" # info response from mserver
106
+ MSG_TUPLE = "["
107
+ MSG_PROMPT = ""
108
+
109
+ REPLY_SIZE = "-1"
110
+ MAX_AUTH_ITERATION = 10 # maximum number of auth iterations (through merovingian) allowed
111
+ MONET_ERROR = -1
112
+
113
+ LANG_SQL = "sql"
114
+ LANG_XQUERY = "xquery"
115
+ XQUERY_OUTPUT_SEQ = true # use MonetDB XQuery's output seq
116
+
117
+ def self.logger=(logger)
118
+ @logger = logger
119
+ end
120
+
121
+ def self.logger
122
+ @logger
123
+ end
124
+
125
+ def self.configurations=(configurations)
126
+ @configurations = configurations.inject({}){|h, (k, v)| h[k.to_s] = v; h}
127
+ end
128
+
129
+ def self.configurations
130
+ @configurations
131
+ end
132
+
133
+ def self.establish_connection(arg)
134
+ config = arg.is_a?(Hash) ? arg : (configurations || {})[arg.to_s]
135
+ if config
136
+ @connection = MonetDB.new.tap do |connection|
137
+ config = {language: "sql", encryption: "SHA1"}.merge(config.inject({}){|h, (k, v)| h[k.to_sym] = v; h})
138
+ connection.instance_variable_set(:@config, config)
139
+ connection.connect *config.values_at(:username, :password, :language, :host, :port, :database, :encryption)
140
+ end
141
+ else
142
+ raise Error, "Unable to establish connection for #{arg.inspect}"
143
+ end
144
+ end
145
+
146
+ def self.connection
147
+ @connection
148
+ end
149
+
150
+ # Establish a new connection.
151
+ # * user : username (default is monetdb)
152
+ # * passwd : password (default is monetdb)
153
+ # * lang : language (default is sql)
154
+ # * host : server hostanme or ip (default is localhost)
155
+ # * port : server port (default is 50000)
156
+ # * db_name : name of the database to connect to
157
+ # * auth_type : hashing function to use during authentication (default is SHA1)
158
+ def connect(username = "monetdb", password = "monetdb", lang = "sql", host = "127.0.0.1", port = "50000", db_name = "test", auth_type = "SHA1")
159
+ # TODO: Handle pools of connections
160
+ @username = username
161
+ @password = password
162
+ @lang = lang
163
+ @host = host
164
+ @port = port
165
+ @db_name = db_name
166
+ @auth_type = auth_type
167
+ @connection = MonetDB::Connection.new(user = @username, passwd = @password, lang = @lang, host = @host, port = @port)
168
+ @connection.connect(@db_name, @auth_type)
169
+ end
170
+
171
+ # Send a <b>user submitted</b> query to the server and store the response.
172
+ #
173
+ # Returns an instance of MonetDB::Data.
174
+ def query(q = "")
175
+ unless @connection.nil?
176
+ @data = MonetDB::Data.new(@connection)
177
+ @data.execute(q)
178
+ end
179
+ @data
180
+ end
181
+
182
+ # Send a <b>user submitted select</b> query to the server and store the response.
183
+ #
184
+ # Returns an array of arrays with casted values.
185
+ def select_rows(qry)
186
+ start = Time.now
187
+ data = query(qry)
188
+ log :info, "\n SQL (#{((Time.now - start) * 1000).round(1)}ms) #{qry}"
189
+ column_types = data.instance_variable_get(:@header)["columns_type"]
190
+ types = data.instance_variable_get(:@header)["columns_name"].collect{|x| column_types[x]}
191
+ data.fetch_all.collect do |array|
192
+ row = []
193
+ array.each_with_index do |value, index|
194
+ row << begin
195
+ unless value == "NULL"
196
+ case types[index]
197
+ when "bigint", "int"
198
+ value.to_i
199
+ when "double"
200
+ value.to_f
201
+ else
202
+ value.force_encoding("UTF-8")
203
+ end
204
+ end
205
+ end
206
+ end
207
+ row
208
+ end
209
+ end
210
+
211
+ # Returns whether a "connection" object exists.
212
+ def connected?
213
+ !@connection.nil?
214
+ end
215
+
216
+ # Reconnect to the server.
217
+ def reconnect
218
+ if @connection != nil
219
+ self.close
220
+ @connection = MonetDB::Connection.new(user = @username, passwd = @password, lang = @lang, host = @host, port = @port)
221
+ @connection.connect(db_name = @db_name, auth_type = @auth_type)
222
+ end
223
+ end
224
+
225
+ # Turn auto commit on/off.
226
+ def auto_commit(flag = true)
227
+ @connection.set_auto_commit(flag)
228
+ end
229
+
230
+ # Returns the current auto commit (on/off) setting.
231
+ def auto_commit?
232
+ @connection.auto_commit?
233
+ end
234
+
235
+ # Returns the name of the last savepoint in a transactions pool.
236
+ def transactions
237
+ @connection.savepoint
238
+ end
239
+
240
+ # Create a new savepoint ID.
241
+ def save
242
+ @connection.transactions.save
243
+ end
244
+
245
+ # Release a savepoint ID.
246
+ def release
247
+ @connection.transactions.release
248
+ end
249
+
250
+ # Close an active connection.
251
+ def close
252
+ @connection.disconnect
253
+ @connection = nil
254
+ end
255
+
256
+ private
257
+
258
+ # Log message.
259
+ def log(type, msg)
260
+ MonetDB.logger.send type, msg if MonetDB.logger
261
+ end
262
+
263
+ end