module DatastaxRails::Schema::Cassandra
Methods for managing the Cassandra
schema
Public Instance Methods
cassandra_index_cql_name(cf, column)
click to toggle source
Computes the expected cassandra index name as reported by CQL.
# File lib/datastax_rails/schema/cassandra.rb, line 103 def cassandra_index_cql_name(cf, column) "#{cf}_#{column}_idx" end
check_missing_schema(model)
click to toggle source
Check for missing columns or columns needing cassandra indexes
# File lib/datastax_rails/schema/cassandra.rb, line 6 def check_missing_schema(model) # rubocop:disable MethodLength count = 0 model.attribute_definitions.each do |attribute, definition| unless column_exists?(model.column_family.to_s, attribute.to_s) count += 1 say "Adding column '#{attribute}'", :subitem DatastaxRails::Cql::AlterColumnFamily.new(model.column_family).add(attribute => definition.cql_type).execute end if definition.options[:cql_index] && !definition.options[:solr_index] unless index_exists?(model.column_family.to_s, attribute.to_s) if index_exists?(model.column_family.to_s, attribute.to_s) count += 1 say "Dropping solr index on #{attribute}", :subitem DatastaxRails::Cql::DropIndex.new(solr_index_cql_name(model.column_family.to_s, attribute.to_s)).execute end count += 1 say "Creating cassandra index on #{attribute}", :subitem DatastaxRails::Cql::CreateIndex.new( cassandra_index_cql_name( model.column_family.to_s, attribute.to_s) ).on(model.column_family.to_s).column(attribute.to_s).execute end elsif definition.options[:cql_index] unless column_exists?(model.column_family.to_s, "__#{attribute}") # Create and populate the new column count += 1 say "Adding column '__#{attribute}'", :subitem DatastaxRails::Cql::AlterColumnFamily.new(model.column_family) .add("__#{attribute}" => definition.cql_type).execute say "Populating column '__#{attribute}' (this might take a while)", :subitem export = "echo \"copy #{model.column_family} (key, #{attribute}) " \ "TO 'dsr_export.csv';\" | cqlsh #{model.current_server}" import = "echo \"copy #{model.column_family} (key, __#{attribute}) " \ "FROM 'dsr_export.csv';\" | cqlsh #{model.current_server}" if system(export) system(import) else @errors << "Looks like you don't have a working cqlsh command in your path.\n" \ "Run the following two commands from a server with cqlsh:\n\n#{export}\n#{import}" end end count += 1 say "Creating cassandra index on __#{attribute}", :subitem DatastaxRails::Cql::CreateIndex.new( cassandra_index_cql_name( model.column_family.to_s, "__#{attribute}") ).on(model.column_family.to_s).column("__#{attribute}").execute end end count end
column_exists?(cf, col)
click to toggle source
Checks the Cassandra
system tables to see if a column exists on a column family
# File lib/datastax_rails/schema/cassandra.rb, line 124 def column_exists?(cf, col) klass = OpenStruct.new(column_family: 'system.schema_columns', default_consistency: 'QUORUM') cql = DatastaxRails::Cql::ColumnFamily.new(klass) results = cql.select('count(*)') .conditions('keyspace_name' => @keyspace, 'columnfamily_name' => cf, 'column_name' => col).execute exists = results.first['count'] > 0 unless exists # We need to check if it's part of an alias (ugh) klass = OpenStruct.new(column_family: 'system.schema_columnfamilies', default_consistency: 'QUORUM') cql = DatastaxRails::Cql::ColumnFamily.new(klass) results = cql.select('column_aliases, key_aliases, value_alias') .conditions('keyspace_name' => @keyspace, 'columnfamily_name' => cf).execute row = results.first exists = row['key_aliases'].include?(col.to_s) || row['column_aliases'].include?(col.to_s) || (row['value_alias'] && row['value_alias'].include?(col.to_s)) end exists end
column_family_exists?(cf)
click to toggle source
Checks the Cassandra
system tables to see if a column family exists
# File lib/datastax_rails/schema/cassandra.rb, line 116 def column_family_exists?(cf) klass = OpenStruct.new(column_family: 'system.schema_columnfamilies', default_consistency: 'QUORUM') cql = DatastaxRails::Cql::ColumnFamily.new(klass) results = cql.select('count(*)').conditions('keyspace_name' => @keyspace, 'columnfamily_name' => cf).execute results.first['count'] > 0 end
create_cql3_column_family(model)
click to toggle source
Creates a CQL3 backed column family
# File lib/datastax_rails/schema/cassandra.rb, line 59 def create_cql3_column_family(model) say 'Creating Column Family via CQL3', :subitem columns = {} model.attribute_definitions.each { |k, col| columns[k] = col.cql_type } pk = model.primary_key.to_s if model.respond_to?(:cluster_by) && model.cluster_by.present? pk += ", #{model.cluster_by}" end cql = DatastaxRails::Cql::CreateColumnFamily.new(model.column_family).primary_key(pk).columns(columns) cql.with(model.create_options) if model.create_options cql.execute end
create_keyspace(keyspace, options = {})
click to toggle source
Creates the named keyspace
# File lib/datastax_rails/schema/cassandra.rb, line 73 def create_keyspace(keyspace, options = {}) opts = { name: keyspace.to_s, strategy_class: 'org.apache.cassandra.locator.NetworkTopologyStrategy' } .with_indifferent_access.merge(options) if keyspace_exists?(keyspace.to_s) say "Keyspace #{keyspace} already exists" return false else cql = DatastaxRails::Cql::CreateKeyspace.new(opts.delete(:name)) cql.strategy_class(opts.delete(:strategy_class)) strategy_options = opts.delete('strategy_options') cql.strategy_options(strategy_options.symbolize_keys) say "Creating keyspace #{keyspace}" cql.execute return true end end
drop_keyspace()
click to toggle source
# File lib/datastax_rails/schema/cassandra.rb, line 92 def drop_keyspace say "Dropping keyspace #{@keyspace}" DatastaxRails::Cql::DropKeyspace.new(@keyspace.to_s).execute end
index_exists?(cf, col)
click to toggle source
Checks the Cassandra
system tables to see if an index exists on a column family
# File lib/datastax_rails/schema/cassandra.rb, line 145 def index_exists?(cf, col) klass = OpenStruct.new(column_family: 'system.schema_columns', default_consistency: 'QUORUM') cql = DatastaxRails::Cql::ColumnFamily.new(klass) results = cql.select('index_name') .conditions('keyspace_name' => @keyspace, 'columnfamily_name' => cf, 'column_name' => col).execute results.first['index_name'] != nil end
keyspace_exists?(keyspace)
click to toggle source
Checks the Cassandra
system tables to see if a keyspace exists
# File lib/datastax_rails/schema/cassandra.rb, line 108 def keyspace_exists?(keyspace) klass = OpenStruct.new(column_family: 'system.schema_keyspaces', default_consistency: 'QUORUM') cql = DatastaxRails::Cql::ColumnFamily.new(klass) results = cql.select('count(*)').conditions('keyspace_name' => keyspace).execute results.first['count'].to_i > 0 end
solr_index_cql_name(cf, column)
click to toggle source
Computes the expected solr index name as reported by CQL.
# File lib/datastax_rails/schema/cassandra.rb, line 98 def solr_index_cql_name(cf, column) "#{@keyspace}_#{cf}_#{column}_index" end