activerecord-jdbccassandra-adapter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 James Thompson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ # activerecord-jdbccassandra-adapter
2
+
3
+ * https://github.com/plainprogrammer/activerecord-jdbccassandra-adapter/
4
+
5
+ ## DESCRIPTION:
6
+
7
+ This is an ActiveRecord driver for Cassandra using JDBC running under JRuby.
@@ -0,0 +1,15 @@
1
+ require 'bundler/gem_helper'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ module Bundler
5
+ class GemHelper
6
+ def guard_already_tagged
7
+ # parent project performs the tag
8
+ end
9
+ def tag_version
10
+ Bundler.ui.confirm "Parent project tagged #{version_tag}"
11
+ yield if block_given?
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,6 @@
1
+ # NOTE: required by AR resolver with 'jdbccassandra' adapter configuration :
2
+ # require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
3
+ # we should make sure a jdbccassandr_connection is setup on ActiveRecord::Base
4
+ require 'arjdbc/cassandra'
5
+ # all setup should be performed in arjdbc/cassandra to avoid circular requires
6
+ # this should not be required from any loads performed by arjdbc/cassandra code
@@ -0,0 +1,3 @@
1
+ # NOTE: here for Bundler to auto-load the gem unless :require => false
2
+ require 'arjdbc'
3
+ require 'arjdbc/cassandra'
@@ -0,0 +1,275 @@
1
+ require 'arjdbc/jdbc'
2
+ require 'arjdbc/cassandra/version'
3
+ require 'arjdbc/cassandra/jdbc_connection'
4
+ require 'arjdbc/cassandra/column'
5
+ require 'arjdbc/cassandra/error'
6
+ require 'arjdbc/cassandra/adapter'
7
+ require 'arjdbc/cassandra/connection_methods'
8
+
9
+ module ArJdbc
10
+ module Cassandra
11
+ def self.extended(adapter)
12
+ adapter.configure_connection
13
+ end
14
+
15
+ def self.column_selector
16
+ [ /cassandra/i, lambda { |_,column| column.extend(::ArJdbc::Cassandra::Column) } ]
17
+ end
18
+
19
+ def self.jdbc_connection_class
20
+ ::ActiveRecord::ConnectionAdapters::CassandraJdbcConnection
21
+ end
22
+
23
+ NATIVE_DATABASE_TYPES = {
24
+ :primary_key => 'uuid PRIMARY KEY',
25
+ :string => { :name => 'varchar' },
26
+ :text => { :name => 'text' },
27
+ :integer => { :name => 'int' },
28
+ :float => { :name => 'float' },
29
+ :decimal => { :name => 'decimal' },
30
+ :datetime => { :name => 'timestamp' },
31
+ :timestamp => { :name => 'timestamp' },
32
+ :time => { :name => 'timestamp' },
33
+ :date => { :name => 'timestamp' },
34
+ :binary => { :name => 'blob' },
35
+ :boolean => { :name => 'boolean' },
36
+ # Extended support for Cassandra types
37
+ :ascii => { :name => 'ascii' },
38
+ :bigint => { :name => 'bigint' },
39
+ :blob => { :name => 'blob' },
40
+ :counter => { :name => 'counter' },
41
+ :double => { :name => 'double' },
42
+ :inet => { :name => 'inet' },
43
+ :timeuuid => { :name => 'timeuuid' },
44
+ :uuid => { :name => 'uuid' },
45
+ :varchar => { :name => 'varchar' },
46
+ :varint => { :name => 'varint' }
47
+ }
48
+
49
+ def native_database_types
50
+ NATIVE_DATABASE_TYPES
51
+ end
52
+
53
+ ADAPTER_NAME = 'Cassandra'.freeze
54
+
55
+ def adapter_name #:nodoc:
56
+ ADAPTER_NAME
57
+ end
58
+
59
+ def self.arel2_visitors(config)
60
+ {
61
+ 'cassandra' => ::Arel::Visitors::ToSql,
62
+ 'jdbccassandra' => ::Arel::Visitors::ToSql
63
+ }
64
+ end
65
+
66
+ def case_sensitive_modifier(node)
67
+ Arel::Nodes::Bin.new(node)
68
+ end
69
+
70
+ def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
71
+ where_sql
72
+ end
73
+
74
+ def supports_migrations?
75
+ false
76
+ end
77
+
78
+ def supports_primary_key? # :nodoc:
79
+ true
80
+ end
81
+
82
+ def supports_bulk_alter? # :nodoc:
83
+ false
84
+ end
85
+
86
+ def supports_index_sort_order? # :nodoc:
87
+ false
88
+ end
89
+
90
+ def supports_transaction_isolation? # :nodoc:
91
+ false
92
+ end
93
+
94
+ def supports_views? # :nodoc:
95
+ false
96
+ end
97
+
98
+ def supports_savepoints? # :nodoc:
99
+ false
100
+ end
101
+
102
+ # DATABASE STATEMENTS ======================================
103
+
104
+ def exec_insert(sql, name, binds)
105
+ execute sql, name, binds
106
+ end
107
+ alias :exec_update :exec_insert
108
+ alias :exec_delete :exec_insert
109
+
110
+ def select(sql, name = nil, binds = [])
111
+ query = sql.gsub(/[0-9a-z_-]+\.\*/i, '*')
112
+ execute query
113
+ end
114
+
115
+ # SCHEMA STATEMENTS ========================================
116
+
117
+ def structure_dump #:nodoc:
118
+ execute('DESCRIBE SCHEMA')
119
+ end
120
+
121
+ def recreate_database(name, options = {}) #:nodoc:
122
+ drop_database(name)
123
+ create_database(name, options)
124
+ end
125
+
126
+ def create_database(name, options = {}) #:nodoc:
127
+ query = "CREATE KEYSPACE #{name} WITH strategy_class = #{options[:strategy_class] || 'SimpleStrategy'}"
128
+
129
+ if options[:strategy_options]
130
+ if options[:strategy_options].is_a?(Array)
131
+ options[:strategy_options].each do |strategy_option|
132
+ query += " AND strategy_options:#{strategy_option}"
133
+ end
134
+ else
135
+ query += " AND strategy_options:#{options[:strategy_options]}"
136
+ end
137
+ end
138
+
139
+ execute query
140
+ end
141
+
142
+ def drop_database(name) #:nodoc:
143
+ execute "DROP KEYSPACE #{name}"
144
+ end
145
+
146
+ def create_table(name, options = {}) #:nodoc:
147
+ td = table_definition
148
+ td.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
149
+
150
+ yield td if block_given?
151
+
152
+ create_sql = "CREATE TABLE #{name} ("
153
+ create_sql << td.to_sql
154
+ create_sql << ") #{options[:options]}"
155
+ execute create_sql
156
+ end
157
+
158
+ def drop_table(name) #:nodoc:
159
+ execute "DROP TABLE #{name}"
160
+ end
161
+
162
+ #def rename_table(name, new_name)
163
+ # execute "RENAME TABLE #{quote_table_name(name)} TO #{quote_table_name(new_name)}"
164
+ #end
165
+
166
+ #def remove_index!(table_name, index_name) #:nodoc:
167
+ # # missing table_name quoting in AR-2.3
168
+ # execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
169
+ #end
170
+
171
+ #def add_column(table_name, column_name, type, options = {})
172
+ # add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
173
+ # add_column_options!(add_column_sql, options)
174
+ # add_column_position!(add_column_sql, options)
175
+ # execute(add_column_sql)
176
+ #end
177
+
178
+ #def change_column_default(table_name, column_name, default) #:nodoc:
179
+ # column = column_for(table_name, column_name)
180
+ # change_column table_name, column_name, column.sql_type, :default => default
181
+ #end
182
+
183
+ #def change_column_null(table_name, column_name, null, default = nil)
184
+ # column = column_for(table_name, column_name)
185
+ #
186
+ # unless null || default.nil?
187
+ # execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
188
+ # end
189
+ #
190
+ # change_column table_name, column_name, column.sql_type, :null => null
191
+ #end
192
+
193
+ #def change_column(table_name, column_name, type, options = {}) #:nodoc:
194
+ # column = column_for(table_name, column_name)
195
+ #
196
+ # unless options_include_default?(options)
197
+ # options[:default] = column.default
198
+ # end
199
+ #
200
+ # unless options.has_key?(:null)
201
+ # options[:null] = column.null
202
+ # end
203
+ #
204
+ # change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
205
+ # add_column_options!(change_column_sql, options)
206
+ # add_column_position!(change_column_sql, options)
207
+ # execute(change_column_sql)
208
+ #end
209
+
210
+ #def rename_column(table_name, column_name, new_column_name) #:nodoc:
211
+ # options = {}
212
+ # if column = columns(table_name).find { |c| c.name == column_name.to_s }
213
+ # options[:default] = column.default
214
+ # options[:null] = column.null
215
+ # else
216
+ # raise ActiveRecord::ActiveRecordError, "No such column: #{table_name}.#{column_name}"
217
+ # end
218
+ # current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
219
+ # rename_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
220
+ # add_column_options!(rename_column_sql, options)
221
+ # execute(rename_column_sql)
222
+ #end
223
+
224
+ #def add_limit_offset!(sql, options) #:nodoc:
225
+ # limit, offset = options[:limit], options[:offset]
226
+ # if limit && offset
227
+ # sql << " LIMIT #{offset.to_i}, #{sanitize_limit(limit)}"
228
+ # elsif limit
229
+ # sql << " LIMIT #{sanitize_limit(limit)}"
230
+ # elsif offset
231
+ # sql << " OFFSET #{offset.to_i}"
232
+ # end
233
+ # sql
234
+ #end
235
+
236
+ #def type_to_sql(type, limit = nil, precision = nil, scale = nil)
237
+ # case type.to_s
238
+ # when 'binary'
239
+ # case limit
240
+ # when 0..0xfff; "varbinary(#{limit})"
241
+ # when nil; "blob"
242
+ # when 0x1000..0xffffffff; "blob(#{limit})"
243
+ # else raise(ActiveRecordError, "No binary type has character length #{limit}")
244
+ # end
245
+ # when 'integer'
246
+ # case limit
247
+ # when 1; 'tinyint'
248
+ # when 2; 'smallint'
249
+ # when 3; 'mediumint'
250
+ # when nil, 4, 11; 'int(11)' # compatibility with MySQL default
251
+ # when 5..8; 'bigint'
252
+ # else raise(ActiveRecordError, "No integer type has byte size #{limit}")
253
+ # end
254
+ # when 'text'
255
+ # case limit
256
+ # when 0..0xff; 'tinytext'
257
+ # when nil, 0x100..0xffff; 'text'
258
+ # when 0x10000..0xffffff; 'mediumtext'
259
+ # when 0x1000000..0xffffffff; 'longtext'
260
+ # else raise(ActiveRecordError, "No text type has character length #{limit}")
261
+ # end
262
+ # else
263
+ # super
264
+ # end
265
+ #end
266
+
267
+ #def add_column_position!(sql, options)
268
+ # if options[:first]
269
+ # sql << " FIRST"
270
+ # elsif options[:after]
271
+ # sql << " AFTER #{quote_column_name(options[:after])}"
272
+ # end
273
+ #end
274
+ end
275
+ end
@@ -0,0 +1,42 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ # Make sure we don't interfere with a pure Ruby version
4
+ remove_const(:CassandraAdapter) if const_defined?(:CassandraAdapter)
5
+
6
+ class CassandraAdapter < JdbcAdapter
7
+ include ::ArJdbc::Cassandra
8
+
9
+ def jdbc_connection_class(spec)
10
+ ::ArJdbc::Cassandra.jdbc_connection_class
11
+ end
12
+
13
+ def jdbc_column_class
14
+ CassandraColumn
15
+ end
16
+ #alias_chained_method :columns, :query_cache, :jdbc_columns
17
+
18
+ # some QUOTING caching :
19
+
20
+ @@quoted_table_names = {}
21
+
22
+ def quote_table_name(name)
23
+ unless quoted = @@quoted_table_names[name]
24
+ quoted = super
25
+ @@quoted_table_names[name] = quoted.freeze
26
+ end
27
+ quoted
28
+ end
29
+
30
+ @@quoted_column_names = {}
31
+
32
+ def quote_column_name(name)
33
+ unless quoted = @@quoted_column_names[name]
34
+ quoted = super
35
+ @@quoted_column_names[name] = quoted.freeze
36
+ end
37
+ quoted
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ class ActiveRecord::Base
2
+ class << self
3
+ def cassandra_connection(config)
4
+ begin
5
+ require 'jdbc/cassandra'
6
+ ::Jdbc::Cassandra.load_driver(:require) if defined?(::Jdbc::Cassandra.load_driver)
7
+ rescue LoadError # assuming driver.jar is on the class-path
8
+ end
9
+
10
+ config[:host] ||= '127.0.0.1'
11
+ config[:port] ||= 9160
12
+ config[:url] ||= "jdbc:cassandra://#{config[:host]}:#{config[:port]}/#{config[:database]}"
13
+ config[:driver] ||= defined?(::Jdbc::Cassandra.driver_name) ? ::Jdbc::Cassandra.driver_name : 'org.apache.cassandra.cql.jdbc.CassandraDriver'
14
+ config[:adapter_class] = ActiveRecord::ConnectionAdapters::CassandraAdapter
15
+ config[:adapter_spec] = ::ArJdbc::Cassandra
16
+
17
+ options = (config[:options] ||= {})
18
+ #options['zeroDateTimeBehavior'] ||= 'convertToNull'
19
+ #options['jdbcCompliantTruncation'] ||= 'false'
20
+ #options['useUnicode'] ||= 'true'
21
+ #options['characterEncoding'] = config[:encoding] || 'utf8'
22
+
23
+ jdbc_connection(config)
24
+ end
25
+ alias_method :jdbccassandra_connection, :cassandra_connection
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ module ArJdbc
2
+ module Cassandra
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-jdbccassandra-adapter
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - James Thompson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord-jdbc-adapter
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 1.2.0
21
+ none: false
22
+ requirement: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.0
27
+ none: false
28
+ prerelease: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ name: jdbc-cassandra
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ~>
35
+ - !ruby/object:Gem::Version
36
+ version: 1.2.5
37
+ none: false
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: 1.2.5
43
+ none: false
44
+ prerelease: false
45
+ type: :runtime
46
+ description: Install this gem to use Cassandra with JRuby on Rails.
47
+ email:
48
+ - james@plainprograms.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - Rakefile
54
+ - README.md
55
+ - LICENSE.txt
56
+ - lib/activerecord-jdbccassandra-adapter.rb
57
+ - lib/active_record/connection_adapters/jdbccassandra_adapter.rb
58
+ - lib/arjdbc/cassandra.rb
59
+ - lib/arjdbc/cassandra/version.rb
60
+ - lib/arjdbc/cassandra/adapter.rb
61
+ - lib/arjdbc/cassandra/connection_methods.rb
62
+ homepage: https://github.com/plainprogrammer/activerecord-jdbccassandra-adapter
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ none: false
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ none: false
80
+ requirements: []
81
+ rubyforge_project: ''
82
+ rubygems_version: 1.8.24
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Cassandra JDBC adapter for JRuby on Rails.
86
+ test_files: []