cequel 1.0.0.rc1 → 1.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/cequel.rb +18 -0
 - data/lib/cequel/errors.rb +8 -4
 - data/lib/cequel/metal.rb +14 -0
 - data/lib/cequel/metal/batch.rb +21 -11
 - data/lib/cequel/metal/batch_manager.rb +74 -0
 - data/lib/cequel/metal/cql_row_specification.rb +19 -6
 - data/lib/cequel/metal/data_set.rb +400 -163
 - data/lib/cequel/metal/deleter.rb +45 -11
 - data/lib/cequel/metal/incrementer.rb +23 -10
 - data/lib/cequel/metal/inserter.rb +19 -6
 - data/lib/cequel/metal/keyspace.rb +82 -159
 - data/lib/cequel/metal/logger.rb +71 -0
 - data/lib/cequel/metal/logging.rb +47 -0
 - data/lib/cequel/metal/new_relic_instrumentation.rb +26 -0
 - data/lib/cequel/metal/row.rb +36 -10
 - data/lib/cequel/metal/row_specification.rb +21 -8
 - data/lib/cequel/metal/statement.rb +30 -6
 - data/lib/cequel/metal/updater.rb +89 -12
 - data/lib/cequel/metal/writer.rb +23 -14
 - data/lib/cequel/record.rb +52 -6
 - data/lib/cequel/record/association_collection.rb +13 -6
 - data/lib/cequel/record/associations.rb +146 -54
 - data/lib/cequel/record/belongs_to_association.rb +34 -7
 - data/lib/cequel/record/bound.rb +69 -12
 - data/lib/cequel/record/bulk_writes.rb +29 -1
 - data/lib/cequel/record/callbacks.rb +22 -6
 - data/lib/cequel/record/collection.rb +273 -36
 - data/lib/cequel/record/configuration_generator.rb +5 -0
 - data/lib/cequel/record/data_set_builder.rb +86 -0
 - data/lib/cequel/record/dirty.rb +11 -8
 - data/lib/cequel/record/errors.rb +38 -4
 - data/lib/cequel/record/has_many_association.rb +42 -9
 - data/lib/cequel/record/lazy_record_collection.rb +39 -10
 - data/lib/cequel/record/mass_assignment.rb +14 -6
 - data/lib/cequel/record/persistence.rb +157 -20
 - data/lib/cequel/record/properties.rb +147 -24
 - data/lib/cequel/record/railtie.rb +15 -2
 - data/lib/cequel/record/record_set.rb +504 -75
 - data/lib/cequel/record/schema.rb +77 -13
 - data/lib/cequel/record/scoped.rb +16 -11
 - data/lib/cequel/record/secondary_indexes.rb +42 -6
 - data/lib/cequel/record/tasks.rb +2 -1
 - data/lib/cequel/record/validations.rb +51 -11
 - data/lib/cequel/schema.rb +9 -0
 - data/lib/cequel/schema/column.rb +172 -33
 - data/lib/cequel/schema/create_table_dsl.rb +62 -31
 - data/lib/cequel/schema/keyspace.rb +106 -7
 - data/lib/cequel/schema/migration_validator.rb +128 -0
 - data/lib/cequel/schema/table.rb +183 -20
 - data/lib/cequel/schema/table_property.rb +92 -34
 - data/lib/cequel/schema/table_reader.rb +45 -15
 - data/lib/cequel/schema/table_synchronizer.rb +101 -43
 - data/lib/cequel/schema/table_updater.rb +114 -19
 - data/lib/cequel/schema/table_writer.rb +31 -13
 - data/lib/cequel/schema/update_table_dsl.rb +71 -40
 - data/lib/cequel/type.rb +214 -53
 - data/lib/cequel/util.rb +6 -9
 - data/lib/cequel/version.rb +2 -1
 - data/spec/examples/record/associations_spec.rb +12 -12
 - data/spec/examples/record/persistence_spec.rb +5 -5
 - data/spec/examples/record/record_set_spec.rb +62 -50
 - data/spec/examples/schema/table_synchronizer_spec.rb +37 -11
 - data/spec/examples/schema/table_updater_spec.rb +3 -3
 - data/spec/examples/spec_helper.rb +2 -11
 - data/spec/examples/type_spec.rb +3 -3
 - metadata +23 -4
 - data/lib/cequel/new_relic_instrumentation.rb +0 -22
 
| 
         @@ -1,56 +1,87 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Cequel
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
2 
     | 
    
         
             
              module Schema
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
                #
         
     | 
| 
      
 4 
     | 
    
         
            +
                # Implements a DSL that can be used to define a table schema
         
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @see Keyspace#create_table
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
       5 
8 
     | 
    
         
             
                class CreateTableDSL < BasicObject
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
                  extend ::Forwardable
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # Evaluate `block` in the context of this DSL, and apply directives to
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # `table`
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # @param table [Table] a table
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @yield block evaluated in the context of the create table DSL
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
       7 
20 
     | 
    
         
             
                  def self.apply(table, &block)
         
     | 
| 
       8 
21 
     | 
    
         
             
                    dsl = new(table)
         
     | 
| 
       9 
22 
     | 
    
         
             
                    dsl.instance_eval(&block)
         
     | 
| 
       10 
23 
     | 
    
         
             
                  end
         
     | 
| 
       11 
24 
     | 
    
         | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # @param table [Table] table to apply directives to
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #
         
     | 
| 
       12 
30 
     | 
    
         
             
                  def initialize(table)
         
     | 
| 
       13 
31 
     | 
    
         
             
                    @table = table
         
     | 
| 
       14 
32 
     | 
    
         
             
                  end
         
     | 
| 
       15 
33 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                   
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @!method partition_key(name, type)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_partition_key)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def_delegator :@table, :add_partition_key, :partition_key
         
     | 
| 
       19 
39 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                   
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 40 
     | 
    
         
            +
                  #
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # @!method key(name, type, clustering_order = nil)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_key)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #
         
     | 
| 
      
 44 
     | 
    
         
            +
                  def_delegator :@table, :add_key, :key
         
     | 
| 
       23 
45 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                   
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
      
 46 
     | 
    
         
            +
                  #
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # @!method column(name, type, options = {})
         
     | 
| 
      
 48 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_data_column)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  #
         
     | 
| 
      
 50 
     | 
    
         
            +
                  def_delegator :@table, :add_data_column, :column
         
     | 
| 
       27 
51 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
      
 52 
     | 
    
         
            +
                  #
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # @!method list(name, type)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_list)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  #
         
     | 
| 
      
 56 
     | 
    
         
            +
                  def_delegator :@table, :add_list, :list
         
     | 
| 
       31 
57 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                   
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                   
     | 
| 
      
 58 
     | 
    
         
            +
                  #
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # @!method set(name, type)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_set)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  #
         
     | 
| 
      
 62 
     | 
    
         
            +
                  def_delegator :@table, :add_set, :set
         
     | 
| 
       35 
63 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                    )
         
     | 
| 
       42 
     | 
    
         
            -
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # @!method map(name, key_type, value_type)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_map)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  #
         
     | 
| 
      
 68 
     | 
    
         
            +
                  def_delegator :@table, :add_map, :map
         
     | 
| 
       43 
69 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                   
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
                   
     | 
| 
      
 70 
     | 
    
         
            +
                  #
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # @!method with(name, value)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  #   (see Cequel::Schema::Table#add_property)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  #
         
     | 
| 
      
 74 
     | 
    
         
            +
                  def_delegator :@table, :add_property, :with
         
     | 
| 
       47 
75 
     | 
    
         | 
| 
      
 76 
     | 
    
         
            +
                  #
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # Direct that this table use "compact storage". This is primarily useful
         
     | 
| 
      
 78 
     | 
    
         
            +
                  # for backwards compatibility with legacy CQL2 table schemas.
         
     | 
| 
      
 79 
     | 
    
         
            +
                  #
         
     | 
| 
      
 80 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 81 
     | 
    
         
            +
                  #
         
     | 
| 
       48 
82 
     | 
    
         
             
                  def compact_storage
         
     | 
| 
       49 
83 
     | 
    
         
             
                    @table.compact_storage = true
         
     | 
| 
       50 
84 
     | 
    
         
             
                  end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
85 
     | 
    
         
             
                end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
86 
     | 
    
         
             
              end
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
87 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,20 +1,44 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Cequel
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
2 
     | 
    
         
             
              module Schema
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
                #
         
     | 
| 
      
 4 
     | 
    
         
            +
                # Provides read/write access to the schema for a keyspace and the tables it
         
     | 
| 
      
 5 
     | 
    
         
            +
                # contains
         
     | 
| 
      
 6 
     | 
    
         
            +
                #
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @deprecated These methods will be exposed directly on
         
     | 
| 
      
 8 
     | 
    
         
            +
                #   {Cequel::Metal::Keyspace} in a future version of Cequel
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
       5 
10 
     | 
    
         
             
                class Keyspace
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
                  #
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # @param keyspace [Keyspace] the keyspace whose schema this object
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   manipulates
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #
         
     | 
| 
       7 
17 
     | 
    
         
             
                  def initialize(keyspace)
         
     | 
| 
       8 
18 
     | 
    
         
             
                    @keyspace = keyspace
         
     | 
| 
       9 
19 
     | 
    
         
             
                  end
         
     | 
| 
       10 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                  #
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # Create this keyspace in the database
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @param options [Options] persistence options for this keyspace.
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @option options [String] :class ("SimpleStrategy") the replication
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   strategy to use for this keyspace
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @option options [Integer] :replication_factor (1) the number of
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #   replicas that should exist for each piece of data
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # @see TK CQL3 CREATE KEYSPACE documentation
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #
         
     | 
| 
       11 
33 
     | 
    
         
             
                  def create!(options = {})
         
     | 
| 
       12 
34 
     | 
    
         
             
                    bare_connection =
         
     | 
| 
       13 
35 
     | 
    
         
             
                      Metal::Keyspace.new(keyspace.configuration.except(:keyspace))
         
     | 
| 
       14 
36 
     | 
    
         | 
| 
       15 
37 
     | 
    
         
             
                    options = options.symbolize_keys
         
     | 
| 
       16 
38 
     | 
    
         
             
                    options[:class] ||= 'SimpleStrategy'
         
     | 
| 
       17 
     | 
    
         
            -
                     
     | 
| 
      
 39 
     | 
    
         
            +
                    if options[:class] == 'SimpleStrategy'
         
     | 
| 
      
 40 
     | 
    
         
            +
                      options[:replication_factor] ||= 1
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
       18 
42 
     | 
    
         
             
                    options_strs = options.map do |name, value|
         
     | 
| 
       19 
43 
     | 
    
         
             
                      "'#{name}': #{CassandraCQL::Statement.quote(value)}"
         
     | 
| 
       20 
44 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -25,34 +49,111 @@ module Cequel 
     | 
|
| 
       25 
49 
     | 
    
         
             
                    CQL
         
     | 
| 
       26 
50 
     | 
    
         
             
                  end
         
     | 
| 
       27 
51 
     | 
    
         | 
| 
      
 52 
     | 
    
         
            +
                  #
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # Drop this keyspace from the database
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 56 
     | 
    
         
            +
                  #
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # @see TK CQL3 DROP KEYSPACE documentation
         
     | 
| 
      
 58 
     | 
    
         
            +
                  #
         
     | 
| 
       28 
59 
     | 
    
         
             
                  def drop!
         
     | 
| 
       29 
60 
     | 
    
         
             
                    keyspace.execute("DROP KEYSPACE #{keyspace.name}")
         
     | 
| 
       30 
61 
     | 
    
         
             
                  end
         
     | 
| 
       31 
62 
     | 
    
         | 
| 
      
 63 
     | 
    
         
            +
                  #
         
     | 
| 
      
 64 
     | 
    
         
            +
                  # @param name [Symbol] name of the table to read
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # @return [Table] object representation of the table schema as it
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #   currently exists in the database
         
     | 
| 
      
 67 
     | 
    
         
            +
                  #
         
     | 
| 
       32 
68 
     | 
    
         
             
                  def read_table(name)
         
     | 
| 
       33 
69 
     | 
    
         
             
                    TableReader.read(keyspace, name)
         
     | 
| 
       34 
70 
     | 
    
         
             
                  end
         
     | 
| 
       35 
71 
     | 
    
         | 
| 
      
 72 
     | 
    
         
            +
                  #
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # Create a table in the keyspace
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # @param name [Symbol] name of the new table to create
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # @yield block evaluated in the context of a {CreateTableDSL}
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 78 
     | 
    
         
            +
                  #
         
     | 
| 
      
 79 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 80 
     | 
    
         
            +
                  #   schema.create_table :posts do
         
     | 
| 
      
 81 
     | 
    
         
            +
                  #     partition_key :blog_subdomain, :text
         
     | 
| 
      
 82 
     | 
    
         
            +
                  #     key :id, :timeuuid
         
     | 
| 
      
 83 
     | 
    
         
            +
                  #
         
     | 
| 
      
 84 
     | 
    
         
            +
                  #     column :title, :text
         
     | 
| 
      
 85 
     | 
    
         
            +
                  #     column :body, :text
         
     | 
| 
      
 86 
     | 
    
         
            +
                  #     column :author_id, :uuid, :index => true
         
     | 
| 
      
 87 
     | 
    
         
            +
                  #
         
     | 
| 
      
 88 
     | 
    
         
            +
                  #     with :caching, :all
         
     | 
| 
      
 89 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 90 
     | 
    
         
            +
                  #
         
     | 
| 
      
 91 
     | 
    
         
            +
                  # @see CreateTableDSL
         
     | 
| 
      
 92 
     | 
    
         
            +
                  #
         
     | 
| 
       36 
93 
     | 
    
         
             
                  def create_table(name, &block)
         
     | 
| 
       37 
94 
     | 
    
         
             
                    table = Table.new(name)
         
     | 
| 
       38 
95 
     | 
    
         
             
                    CreateTableDSL.apply(table, &block)
         
     | 
| 
       39 
96 
     | 
    
         
             
                    TableWriter.apply(keyspace, table)
         
     | 
| 
       40 
97 
     | 
    
         
             
                  end
         
     | 
| 
       41 
98 
     | 
    
         | 
| 
      
 99 
     | 
    
         
            +
                  #
         
     | 
| 
      
 100 
     | 
    
         
            +
                  # Make changes to an existing table in the keyspace
         
     | 
| 
      
 101 
     | 
    
         
            +
                  #
         
     | 
| 
      
 102 
     | 
    
         
            +
                  # @param name [Symbol] the name of the table to alter
         
     | 
| 
      
 103 
     | 
    
         
            +
                  # @yield block evaluated in the context of an {UpdateTableDSL}
         
     | 
| 
      
 104 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 105 
     | 
    
         
            +
                  #
         
     | 
| 
      
 106 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 107 
     | 
    
         
            +
                  #   schema.alter_table :posts do
         
     | 
| 
      
 108 
     | 
    
         
            +
                  #     add_set :categories, :text
         
     | 
| 
      
 109 
     | 
    
         
            +
                  #     rename_column :author_id, :author_uuid
         
     | 
| 
      
 110 
     | 
    
         
            +
                  #     create_index :title
         
     | 
| 
      
 111 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 112 
     | 
    
         
            +
                  #
         
     | 
| 
      
 113 
     | 
    
         
            +
                  # @see UpdateTableDSL
         
     | 
| 
      
 114 
     | 
    
         
            +
                  #
         
     | 
| 
       42 
115 
     | 
    
         
             
                  def alter_table(name, &block)
         
     | 
| 
       43 
116 
     | 
    
         
             
                    updater = TableUpdater.apply(keyspace, name) do |updater|
         
     | 
| 
       44 
117 
     | 
    
         
             
                      UpdateTableDSL.apply(updater, &block)
         
     | 
| 
       45 
118 
     | 
    
         
             
                    end
         
     | 
| 
       46 
119 
     | 
    
         
             
                  end
         
     | 
| 
       47 
120 
     | 
    
         | 
| 
      
 121 
     | 
    
         
            +
                  #
         
     | 
| 
      
 122 
     | 
    
         
            +
                  # Remove all data from this table. Truncating a table can be much slower
         
     | 
| 
      
 123 
     | 
    
         
            +
                  # than simply iterating over its keys and issuing `DELETE` statements,
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # particularly if the table does not have many rows. Truncating is
         
     | 
| 
      
 125 
     | 
    
         
            +
                  # equivalent to dropping a table and then recreating it
         
     | 
| 
      
 126 
     | 
    
         
            +
                  #
         
     | 
| 
      
 127 
     | 
    
         
            +
                  # @param name [Symbol] name of the table to truncate.
         
     | 
| 
      
 128 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 129 
     | 
    
         
            +
                  #
         
     | 
| 
       48 
130 
     | 
    
         
             
                  def truncate_table(name)
         
     | 
| 
       49 
131 
     | 
    
         
             
                    keyspace.execute("TRUNCATE #{name}")
         
     | 
| 
       50 
132 
     | 
    
         
             
                  end
         
     | 
| 
       51 
133 
     | 
    
         | 
| 
      
 134 
     | 
    
         
            +
                  #
         
     | 
| 
      
 135 
     | 
    
         
            +
                  # Drop this table from the keyspace
         
     | 
| 
      
 136 
     | 
    
         
            +
                  #
         
     | 
| 
      
 137 
     | 
    
         
            +
                  # @param name [Symbol] name of the table to drop
         
     | 
| 
      
 138 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 139 
     | 
    
         
            +
                  #
         
     | 
| 
       52 
140 
     | 
    
         
             
                  def drop_table(name)
         
     | 
| 
       53 
141 
     | 
    
         
             
                    keyspace.execute("DROP TABLE #{name}")
         
     | 
| 
       54 
142 
     | 
    
         
             
                  end
         
     | 
| 
       55 
143 
     | 
    
         | 
| 
      
 144 
     | 
    
         
            +
                  #
         
     | 
| 
      
 145 
     | 
    
         
            +
                  # Create or update a table to match a given schema structure. The desired
         
     | 
| 
      
 146 
     | 
    
         
            +
                  # schema structure is defined by the directives given in the block; this
         
     | 
| 
      
 147 
     | 
    
         
            +
                  # is then compared to the existing table in the database (if it is
         
     | 
| 
      
 148 
     | 
    
         
            +
                  # defined at all), and then the table is created or altered accordingly.
         
     | 
| 
      
 149 
     | 
    
         
            +
                  #
         
     | 
| 
      
 150 
     | 
    
         
            +
                  # @param name [Symbol] name of the table to synchronize
         
     | 
| 
      
 151 
     | 
    
         
            +
                  # @yield (see #create_table)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 153 
     | 
    
         
            +
                  # @raise (see TableSynchronizer#apply)
         
     | 
| 
      
 154 
     | 
    
         
            +
                  #
         
     | 
| 
      
 155 
     | 
    
         
            +
                  # @see #create_table Example of DSL usage
         
     | 
| 
      
 156 
     | 
    
         
            +
                  #
         
     | 
| 
       56 
157 
     | 
    
         
             
                  def sync_table(name, &block)
         
     | 
| 
       57 
158 
     | 
    
         
             
                    existing = read_table(name)
         
     | 
| 
       58 
159 
     | 
    
         
             
                    updated = Table.new(name)
         
     | 
| 
         @@ -62,10 +163,8 @@ module Cequel 
     | 
|
| 
       62 
163 
     | 
    
         
             
                  alias_method :synchronize_table, :sync_table
         
     | 
| 
       63 
164 
     | 
    
         | 
| 
       64 
165 
     | 
    
         
             
                  protected
         
     | 
| 
       65 
     | 
    
         
            -
                  attr_reader :keyspace
         
     | 
| 
       66 
166 
     | 
    
         | 
| 
      
 167 
     | 
    
         
            +
                  attr_reader :keyspace
         
     | 
| 
       67 
168 
     | 
    
         
             
                end
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
169 
     | 
    
         
             
              end
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
170 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,128 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Cequel
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Schema
         
     | 
| 
      
 3 
     | 
    
         
            +
                #
         
     | 
| 
      
 4 
     | 
    
         
            +
                # This is a utility class to test that it is possible to perform a given
         
     | 
| 
      
 5 
     | 
    
         
            +
                # table schema migration
         
     | 
| 
      
 6 
     | 
    
         
            +
                #
         
     | 
| 
      
 7 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 8 
     | 
    
         
            +
                #
         
     | 
| 
      
 9 
     | 
    
         
            +
                class MigrationValidator
         
     | 
| 
      
 10 
     | 
    
         
            +
                  extend Forwardable
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # Check for various impossible schema changes and raise if any are found
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # @param (see #initialize)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # @raise (see #validate)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.validate!(synchronizer)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    new(synchronizer).validate!
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @param synchronizer [TableSynchronizer] the synchronizer to validate
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
      
 25 
     | 
    
         
            +
                  def initialize(synchronizer)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @synchronizer = synchronizer
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  #
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # Check for various impossible schema changes and raise if any are found
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # @raise [InvalidSchemaMigration] if it is impossible to modify existing
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   table to match desired schema
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  def validate!
         
     | 
| 
      
 36 
     | 
    
         
            +
                    assert_keys_match!
         
     | 
| 
      
 37 
     | 
    
         
            +
                    assert_data_columns_match!
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  private
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  attr_reader :synchronizer
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def_delegators :synchronizer, :each_key_pair,
         
     | 
| 
      
 44 
     | 
    
         
            +
                                 :each_clustering_column_pair, :each_data_column_pair,
         
     | 
| 
      
 45 
     | 
    
         
            +
                                 :existing, :updated
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def assert_keys_match!
         
     | 
| 
      
 48 
     | 
    
         
            +
                    assert_partition_keys_match!
         
     | 
| 
      
 49 
     | 
    
         
            +
                    assert_clustering_columns_match!
         
     | 
| 
      
 50 
     | 
    
         
            +
                    assert_same_key_types!
         
     | 
| 
      
 51 
     | 
    
         
            +
                    assert_same_clustering_order!
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  def assert_same_key_types!
         
     | 
| 
      
 55 
     | 
    
         
            +
                    each_key_pair do |old_key, new_key|
         
     | 
| 
      
 56 
     | 
    
         
            +
                      if old_key.type != new_key.type
         
     | 
| 
      
 57 
     | 
    
         
            +
                        fail InvalidSchemaMigration,
         
     | 
| 
      
 58 
     | 
    
         
            +
                             "Can't change type of key column #{old_key.name} from " \
         
     | 
| 
      
 59 
     | 
    
         
            +
                             "#{old_key.type} to #{new_key.type}"
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def assert_same_clustering_order!
         
     | 
| 
      
 65 
     | 
    
         
            +
                    each_clustering_column_pair do |old_key, new_key|
         
     | 
| 
      
 66 
     | 
    
         
            +
                      if old_key.clustering_order != new_key.clustering_order
         
     | 
| 
      
 67 
     | 
    
         
            +
                        fail InvalidSchemaMigration,
         
     | 
| 
      
 68 
     | 
    
         
            +
                             "Can't change the clustering order of #{old_key.name} from " \
         
     | 
| 
      
 69 
     | 
    
         
            +
                             "#{old_key.clustering_order} to #{new_key.clustering_order}"
         
     | 
| 
      
 70 
     | 
    
         
            +
                      end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  def assert_partition_keys_match!
         
     | 
| 
      
 75 
     | 
    
         
            +
                    if existing.partition_key_column_count !=
         
     | 
| 
      
 76 
     | 
    
         
            +
                        updated.partition_key_column_count
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                      fail InvalidSchemaMigration,
         
     | 
| 
      
 79 
     | 
    
         
            +
                           "Existing partition keys " \
         
     | 
| 
      
 80 
     | 
    
         
            +
                           "#{existing.partition_key_column_names.join(',')} " \
         
     | 
| 
      
 81 
     | 
    
         
            +
                           "differ from specified partition keys " \
         
     | 
| 
      
 82 
     | 
    
         
            +
                           "#{updated.partition_key_column_names.join(',')}"
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  def assert_clustering_columns_match!
         
     | 
| 
      
 87 
     | 
    
         
            +
                    if existing.clustering_column_count != updated.clustering_column_count
         
     | 
| 
      
 88 
     | 
    
         
            +
                      fail InvalidSchemaMigration,
         
     | 
| 
      
 89 
     | 
    
         
            +
                           "Existing clustering columns " \
         
     | 
| 
      
 90 
     | 
    
         
            +
                           "#{existing.clustering_column_names.join(',')} " \
         
     | 
| 
      
 91 
     | 
    
         
            +
                           "differ from specified clustering keys " \
         
     | 
| 
      
 92 
     | 
    
         
            +
                           "#{updated.clustering_column_names.join(',')}"
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  def assert_data_columns_match!
         
     | 
| 
      
 97 
     | 
    
         
            +
                    each_data_column_pair do |old_column, new_column|
         
     | 
| 
      
 98 
     | 
    
         
            +
                      if old_column && new_column
         
     | 
| 
      
 99 
     | 
    
         
            +
                        assert_valid_type_transition!(old_column, new_column)
         
     | 
| 
      
 100 
     | 
    
         
            +
                        assert_same_column_structure!(old_column, new_column)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      end
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
                  end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  def assert_valid_type_transition!(old_column, new_column)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    if old_column.type != new_column.type
         
     | 
| 
      
 107 
     | 
    
         
            +
                      valid_new_types = old_column.type.compatible_types
         
     | 
| 
      
 108 
     | 
    
         
            +
                      unless valid_new_types.include?(new_column.type)
         
     | 
| 
      
 109 
     | 
    
         
            +
                        fail InvalidSchemaMigration,
         
     | 
| 
      
 110 
     | 
    
         
            +
                             "Can't change #{old_column.name} from " \
         
     | 
| 
      
 111 
     | 
    
         
            +
                             "#{old_column.type} to #{new_column.type}. " \
         
     | 
| 
      
 112 
     | 
    
         
            +
                             "#{old_column.type} columns may only be altered to " \
         
     | 
| 
      
 113 
     | 
    
         
            +
                             "#{valid_new_types.to_sentence}."
         
     | 
| 
      
 114 
     | 
    
         
            +
                      end
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  def assert_same_column_structure!(old_column, new_column)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    if old_column.class != new_column.class
         
     | 
| 
      
 120 
     | 
    
         
            +
                      fail InvalidSchemaMigration,
         
     | 
| 
      
 121 
     | 
    
         
            +
                           "Can't change #{old_column.name} from " \
         
     | 
| 
      
 122 
     | 
    
         
            +
                           "#{old_column.class.name.demodulize} to " \
         
     | 
| 
      
 123 
     | 
    
         
            +
                           "#{new_column.class.name.demodulize}"
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
      
 127 
     | 
    
         
            +
              end
         
     | 
| 
      
 128 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/cequel/schema/table.rb
    CHANGED
    
    | 
         @@ -1,19 +1,42 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'stringio'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Cequel
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
4 
     | 
    
         
             
              module Schema
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
                #
         
     | 
| 
      
 6 
     | 
    
         
            +
                # An object representation of a CQL3 table schema.
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @see Keyspace#read_table
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
       7 
10 
     | 
    
         
             
                class Table
         
     | 
| 
      
 11 
     | 
    
         
            +
                  STORAGE_PROPERTIES = %w[
         
     | 
| 
      
 12 
     | 
    
         
            +
                    bloom_filter_fp_chance caching comment compaction compression
         
     | 
| 
      
 13 
     | 
    
         
            +
                    dclocal_read_repair_chance gc_grace_seconds read_repair_chance
         
     | 
| 
      
 14 
     | 
    
         
            +
                    replicate_on_write
         
     | 
| 
      
 15 
     | 
    
         
            +
                  ]
         
     | 
| 
       8 
16 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                   
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # @return [Symbol] the name of the table
         
     | 
| 
      
 18 
     | 
    
         
            +
                  attr_reader :name
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # @return [Array<Column>] all columns defined on the table
         
     | 
| 
      
 20 
     | 
    
         
            +
                  attr_reader :columns
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # @return [Array<PartitionKey>] partition key columns defined on the
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #   table
         
     | 
| 
      
 23 
     | 
    
         
            +
                  attr_reader :partition_key_columns
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @return [Array<ClusteringColumn>] clustering columns defined on the
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #   table
         
     | 
| 
      
 26 
     | 
    
         
            +
                  attr_reader :clustering_columns
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @return [Array<DataColumn,CollectionColumn>] data columns and
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #   collection columns defined on the table
         
     | 
| 
      
 29 
     | 
    
         
            +
                  attr_reader :data_columns
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # @return [Hash] storage properties defined on the table
         
     | 
| 
      
 31 
     | 
    
         
            +
                  attr_reader :properties
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # @return [Boolean] `true` if this table is configured with compact
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   storage
         
     | 
| 
       15 
34 
     | 
    
         
             
                  attr_writer :compact_storage
         
     | 
| 
       16 
35 
     | 
    
         | 
| 
      
 36 
     | 
    
         
            +
                  #
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @param name [Symbol] the name of the table
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #
         
     | 
| 
       17 
40 
     | 
    
         
             
                  def initialize(name)
         
     | 
| 
       18 
41 
     | 
    
         
             
                    @name = name
         
     | 
| 
       19 
42 
     | 
    
         
             
                    @partition_key_columns, @clustering_columns, @data_columns = [], [], []
         
     | 
| 
         @@ -21,11 +44,24 @@ module Cequel 
     | 
|
| 
       21 
44 
     | 
    
         
             
                    @properties = ActiveSupport::HashWithIndifferentAccess.new
         
     | 
| 
       22 
45 
     | 
    
         
             
                  end
         
     | 
| 
       23 
46 
     | 
    
         | 
| 
      
 47 
     | 
    
         
            +
                  #
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # Define a key column. If this is the first key column defined, it will
         
     | 
| 
      
 49 
     | 
    
         
            +
                  # be a partition key; otherwise, it will be a clustering column.
         
     | 
| 
      
 50 
     | 
    
         
            +
                  #
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # @param name [Symbol] the name of the column
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # @param type [Symbol,Type] the type for the column
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # @param clustering_order [:asc,:desc] whether rows should be in
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #   ascending or descending order by this column. Only meaningful for
         
     | 
| 
      
 55 
     | 
    
         
            +
                  #   clustering columns.
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  #
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # @see #add_partition_key
         
     | 
| 
      
 59 
     | 
    
         
            +
                  #
         
     | 
| 
       24 
60 
     | 
    
         
             
                  def add_key(name, type, clustering_order = nil)
         
     | 
| 
       25 
61 
     | 
    
         
             
                    if @partition_key_columns.empty?
         
     | 
| 
       26 
62 
     | 
    
         
             
                      unless clustering_order.nil?
         
     | 
| 
       27 
     | 
    
         
            -
                         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 63 
     | 
    
         
            +
                        fail ArgumentError,
         
     | 
| 
      
 64 
     | 
    
         
            +
                             "Can't set clustering order for partition key #{name}"
         
     | 
| 
       29 
65 
     | 
    
         
             
                      end
         
     | 
| 
       30 
66 
     | 
    
         
             
                      add_partition_key(name, type)
         
     | 
| 
       31 
67 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -33,82 +69,212 @@ module Cequel 
     | 
|
| 
       33 
69 
     | 
    
         
             
                    end
         
     | 
| 
       34 
70 
     | 
    
         
             
                  end
         
     | 
| 
       35 
71 
     | 
    
         | 
| 
      
 72 
     | 
    
         
            +
                  #
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # Define a partition key for the table
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # @param name [Symbol] the name of the column
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # @param type [Symbol,Type] the type for the column
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 78 
     | 
    
         
            +
                  #
         
     | 
| 
       36 
79 
     | 
    
         
             
                  def add_partition_key(name, type)
         
     | 
| 
       37 
80 
     | 
    
         
             
                    PartitionKey.new(name, type(type)).tap do |column|
         
     | 
| 
       38 
81 
     | 
    
         
             
                      @partition_key_columns << add_column(column)
         
     | 
| 
       39 
82 
     | 
    
         
             
                    end
         
     | 
| 
       40 
83 
     | 
    
         
             
                  end
         
     | 
| 
       41 
84 
     | 
    
         | 
| 
      
 85 
     | 
    
         
            +
                  #
         
     | 
| 
      
 86 
     | 
    
         
            +
                  # Define a clustering column for the table
         
     | 
| 
      
 87 
     | 
    
         
            +
                  #
         
     | 
| 
      
 88 
     | 
    
         
            +
                  # @param (see #add_key)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 90 
     | 
    
         
            +
                  #
         
     | 
| 
       42 
91 
     | 
    
         
             
                  def add_clustering_column(name, type, clustering_order = nil)
         
     | 
| 
       43 
     | 
    
         
            -
                    ClusteringColumn.new(name, type(type), clustering_order) 
     | 
| 
       44 
     | 
    
         
            -
                      @clustering_columns << add_column(column)
         
     | 
| 
       45 
     | 
    
         
            -
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                    ClusteringColumn.new(name, type(type), clustering_order)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      .tap { |column| @clustering_columns << add_column(column) }
         
     | 
| 
       46 
94 
     | 
    
         
             
                  end
         
     | 
| 
       47 
95 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                   
     | 
| 
      
 96 
     | 
    
         
            +
                  #
         
     | 
| 
      
 97 
     | 
    
         
            +
                  # Define a data column on the table
         
     | 
| 
      
 98 
     | 
    
         
            +
                  #
         
     | 
| 
      
 99 
     | 
    
         
            +
                  # @param name [Symbol] name of the column
         
     | 
| 
      
 100 
     | 
    
         
            +
                  # @param type [Type] type for the column
         
     | 
| 
      
 101 
     | 
    
         
            +
                  # @param options [Options] options for the column
         
     | 
| 
      
 102 
     | 
    
         
            +
                  # @option options [Boolean,Symbol] :index (nil) name of a secondary index
         
     | 
| 
      
 103 
     | 
    
         
            +
                  #   to apply to the column, or `true` to infer an index name by
         
     | 
| 
      
 104 
     | 
    
         
            +
                  #   convention
         
     | 
| 
      
 105 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 106 
     | 
    
         
            +
                  #
         
     | 
| 
      
 107 
     | 
    
         
            +
                  def add_data_column(name, type, options = {})
         
     | 
| 
      
 108 
     | 
    
         
            +
                    options = {index: options} unless options.is_a?(Hash)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    index_name = options[:index]
         
     | 
| 
       49 
110 
     | 
    
         
             
                    index_name = :"#{@name}_#{name}_idx" if index_name == true
         
     | 
| 
       50 
     | 
    
         
            -
                    DataColumn.new(name, type(type), index_name) 
     | 
| 
       51 
     | 
    
         
            -
                      tap { |column| @data_columns << add_column(column) }
         
     | 
| 
      
 111 
     | 
    
         
            +
                    DataColumn.new(name, type(type), index_name)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      .tap { |column| @data_columns << add_column(column) }
         
     | 
| 
       52 
113 
     | 
    
         
             
                  end
         
     | 
| 
       53 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
                  #
         
     | 
| 
      
 116 
     | 
    
         
            +
                  # Define a list column on the table
         
     | 
| 
      
 117 
     | 
    
         
            +
                  #
         
     | 
| 
      
 118 
     | 
    
         
            +
                  # @param name [Symbol] name of the list
         
     | 
| 
      
 119 
     | 
    
         
            +
                  # @param type [Symbol,Type] type of the list's elements
         
     | 
| 
      
 120 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 121 
     | 
    
         
            +
                  #
         
     | 
| 
      
 122 
     | 
    
         
            +
                  # @see List
         
     | 
| 
      
 123 
     | 
    
         
            +
                  #
         
     | 
| 
       54 
124 
     | 
    
         
             
                  def add_list(name, type)
         
     | 
| 
       55 
125 
     | 
    
         
             
                    List.new(name, type(type)).tap do |column|
         
     | 
| 
       56 
126 
     | 
    
         
             
                      @data_columns << add_column(column)
         
     | 
| 
       57 
127 
     | 
    
         
             
                    end
         
     | 
| 
       58 
128 
     | 
    
         
             
                  end
         
     | 
| 
       59 
129 
     | 
    
         | 
| 
      
 130 
     | 
    
         
            +
                  #
         
     | 
| 
      
 131 
     | 
    
         
            +
                  # Define a set column on the table
         
     | 
| 
      
 132 
     | 
    
         
            +
                  #
         
     | 
| 
      
 133 
     | 
    
         
            +
                  # @param name [Symbol] name of the set
         
     | 
| 
      
 134 
     | 
    
         
            +
                  # @param type [Symbol,Type] type of the set's elements
         
     | 
| 
      
 135 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 136 
     | 
    
         
            +
                  #
         
     | 
| 
      
 137 
     | 
    
         
            +
                  # @see Set
         
     | 
| 
      
 138 
     | 
    
         
            +
                  #
         
     | 
| 
       60 
139 
     | 
    
         
             
                  def add_set(name, type)
         
     | 
| 
       61 
140 
     | 
    
         
             
                    Set.new(name, type(type)).tap do |column|
         
     | 
| 
       62 
141 
     | 
    
         
             
                      @data_columns << add_column(column)
         
     | 
| 
       63 
142 
     | 
    
         
             
                    end
         
     | 
| 
       64 
143 
     | 
    
         
             
                  end
         
     | 
| 
       65 
144 
     | 
    
         | 
| 
      
 145 
     | 
    
         
            +
                  #
         
     | 
| 
      
 146 
     | 
    
         
            +
                  # Define a map column on the table
         
     | 
| 
      
 147 
     | 
    
         
            +
                  #
         
     | 
| 
      
 148 
     | 
    
         
            +
                  # @param name [Symbol] name of the set
         
     | 
| 
      
 149 
     | 
    
         
            +
                  # @param key_type [Symbol,Type] type of the map's keys
         
     | 
| 
      
 150 
     | 
    
         
            +
                  # @param value_type [Symbol,Type] type of the map's values
         
     | 
| 
      
 151 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 152 
     | 
    
         
            +
                  #
         
     | 
| 
      
 153 
     | 
    
         
            +
                  # @see Map
         
     | 
| 
      
 154 
     | 
    
         
            +
                  #
         
     | 
| 
       66 
155 
     | 
    
         
             
                  def add_map(name, key_type, value_type)
         
     | 
| 
       67 
156 
     | 
    
         
             
                    Map.new(name, type(key_type), type(value_type)).tap do |column|
         
     | 
| 
       68 
157 
     | 
    
         
             
                      @data_columns << add_column(column)
         
     | 
| 
       69 
158 
     | 
    
         
             
                    end
         
     | 
| 
       70 
159 
     | 
    
         
             
                  end
         
     | 
| 
       71 
160 
     | 
    
         | 
| 
      
 161 
     | 
    
         
            +
                  #
         
     | 
| 
      
 162 
     | 
    
         
            +
                  # Define a storage property for the table
         
     | 
| 
      
 163 
     | 
    
         
            +
                  #
         
     | 
| 
      
 164 
     | 
    
         
            +
                  # @param name [Symbol] name of the property
         
     | 
| 
      
 165 
     | 
    
         
            +
                  # @param value value for the property
         
     | 
| 
      
 166 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 167 
     | 
    
         
            +
                  #
         
     | 
| 
      
 168 
     | 
    
         
            +
                  # @see STORAGE_PROPERTIES List of storage property names
         
     | 
| 
      
 169 
     | 
    
         
            +
                  # @see TK list of CQL3 table storage properties
         
     | 
| 
      
 170 
     | 
    
         
            +
                  #
         
     | 
| 
       72 
171 
     | 
    
         
             
                  def add_property(name, value)
         
     | 
| 
       73 
     | 
    
         
            -
                    TableProperty. 
     | 
| 
      
 172 
     | 
    
         
            +
                    TableProperty.build(name, value).tap do |property|
         
     | 
| 
       74 
173 
     | 
    
         
             
                      @properties[name] = property
         
     | 
| 
       75 
174 
     | 
    
         
             
                    end
         
     | 
| 
       76 
175 
     | 
    
         
             
                  end
         
     | 
| 
       77 
176 
     | 
    
         | 
| 
      
 177 
     | 
    
         
            +
                  #
         
     | 
| 
      
 178 
     | 
    
         
            +
                  # @param name [Symbol] name of column to look up
         
     | 
| 
      
 179 
     | 
    
         
            +
                  # @return [Column] column defined on table with given name
         
     | 
| 
      
 180 
     | 
    
         
            +
                  #
         
     | 
| 
       78 
181 
     | 
    
         
             
                  def column(name)
         
     | 
| 
       79 
182 
     | 
    
         
             
                    columns_by_name[name.to_sym]
         
     | 
| 
       80 
183 
     | 
    
         
             
                  end
         
     | 
| 
       81 
184 
     | 
    
         | 
| 
      
 185 
     | 
    
         
            +
                  #
         
     | 
| 
      
 186 
     | 
    
         
            +
                  # @return [Array<Column>] all key columns (partition + clustering)
         
     | 
| 
      
 187 
     | 
    
         
            +
                  #
         
     | 
| 
       82 
188 
     | 
    
         
             
                  def key_columns
         
     | 
| 
       83 
189 
     | 
    
         
             
                    @partition_key_columns + @clustering_columns
         
     | 
| 
       84 
190 
     | 
    
         
             
                  end
         
     | 
| 
       85 
191 
     | 
    
         | 
| 
      
 192 
     | 
    
         
            +
                  #
         
     | 
| 
      
 193 
     | 
    
         
            +
                  # @return [Array<Symbol>] names of all key columns (partition +
         
     | 
| 
      
 194 
     | 
    
         
            +
                  #   clustering)
         
     | 
| 
      
 195 
     | 
    
         
            +
                  #
         
     | 
| 
       86 
196 
     | 
    
         
             
                  def key_column_names
         
     | 
| 
       87 
197 
     | 
    
         
             
                    key_columns.map { |key| key.name }
         
     | 
| 
       88 
198 
     | 
    
         
             
                  end
         
     | 
| 
       89 
199 
     | 
    
         | 
| 
      
 200 
     | 
    
         
            +
                  #
         
     | 
| 
      
 201 
     | 
    
         
            +
                  # @return [Integer] total number of key columns
         
     | 
| 
      
 202 
     | 
    
         
            +
                  #
         
     | 
| 
      
 203 
     | 
    
         
            +
                  def key_column_count
         
     | 
| 
      
 204 
     | 
    
         
            +
                    key_columns.length
         
     | 
| 
      
 205 
     | 
    
         
            +
                  end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                  #
         
     | 
| 
      
 208 
     | 
    
         
            +
                  # @return [Array<Symbol>] names of partition key columns
         
     | 
| 
      
 209 
     | 
    
         
            +
                  #
         
     | 
| 
      
 210 
     | 
    
         
            +
                  def partition_key_column_names
         
     | 
| 
      
 211 
     | 
    
         
            +
                    partition_key_columns.map { |key| key.name }
         
     | 
| 
      
 212 
     | 
    
         
            +
                  end
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                  #
         
     | 
| 
      
 215 
     | 
    
         
            +
                  # @return [Integer] number of partition key columns
         
     | 
| 
      
 216 
     | 
    
         
            +
                  #
         
     | 
| 
      
 217 
     | 
    
         
            +
                  def partition_key_column_count
         
     | 
| 
      
 218 
     | 
    
         
            +
                    partition_key_columns.length
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                  #
         
     | 
| 
      
 222 
     | 
    
         
            +
                  # @return [Array<Symbol>] names of clustering columns
         
     | 
| 
      
 223 
     | 
    
         
            +
                  #
         
     | 
| 
      
 224 
     | 
    
         
            +
                  def clustering_column_names
         
     | 
| 
      
 225 
     | 
    
         
            +
                    clustering_columns.map { |key| key.name }
         
     | 
| 
      
 226 
     | 
    
         
            +
                  end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                  #
         
     | 
| 
      
 229 
     | 
    
         
            +
                  # @return [Integer] number of clustering columns
         
     | 
| 
      
 230 
     | 
    
         
            +
                  #
         
     | 
| 
      
 231 
     | 
    
         
            +
                  def clustering_column_count
         
     | 
| 
      
 232 
     | 
    
         
            +
                    clustering_columns.length
         
     | 
| 
      
 233 
     | 
    
         
            +
                  end
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                  #
         
     | 
| 
      
 236 
     | 
    
         
            +
                  # @param name [Symbol] name of partition key column to look up
         
     | 
| 
      
 237 
     | 
    
         
            +
                  # @return [PartitionKey] partition key column with given name
         
     | 
| 
      
 238 
     | 
    
         
            +
                  #
         
     | 
| 
       90 
239 
     | 
    
         
             
                  def partition_key(name)
         
     | 
| 
       91 
240 
     | 
    
         
             
                    @partition_key_columns.find { |column| column.name == name }
         
     | 
| 
       92 
241 
     | 
    
         
             
                  end
         
     | 
| 
       93 
242 
     | 
    
         | 
| 
      
 243 
     | 
    
         
            +
                  #
         
     | 
| 
      
 244 
     | 
    
         
            +
                  # @param name [Symbol] name of clustering column to look up
         
     | 
| 
      
 245 
     | 
    
         
            +
                  # @return [ClusteringColumn] clustering column with given name
         
     | 
| 
      
 246 
     | 
    
         
            +
                  #
         
     | 
| 
       94 
247 
     | 
    
         
             
                  def clustering_column(name)
         
     | 
| 
       95 
248 
     | 
    
         
             
                    @clustering_columns.find { |column| column.name == name }
         
     | 
| 
       96 
249 
     | 
    
         
             
                  end
         
     | 
| 
       97 
250 
     | 
    
         | 
| 
      
 251 
     | 
    
         
            +
                  #
         
     | 
| 
      
 252 
     | 
    
         
            +
                  # @param name [Symbol] name of data column to look up
         
     | 
| 
      
 253 
     | 
    
         
            +
                  # @return [DataColumn,CollectionColumn] data column or collection column
         
     | 
| 
      
 254 
     | 
    
         
            +
                  #   with given name
         
     | 
| 
      
 255 
     | 
    
         
            +
                  #
         
     | 
| 
       98 
256 
     | 
    
         
             
                  def data_column(name)
         
     | 
| 
       99 
257 
     | 
    
         
             
                    name = name.to_sym
         
     | 
| 
       100 
258 
     | 
    
         
             
                    @data_columns.find { |column| column.name == name }
         
     | 
| 
       101 
259 
     | 
    
         
             
                  end
         
     | 
| 
       102 
260 
     | 
    
         | 
| 
      
 261 
     | 
    
         
            +
                  #
         
     | 
| 
      
 262 
     | 
    
         
            +
                  # @param name [Symbol] name of property to look up
         
     | 
| 
      
 263 
     | 
    
         
            +
                  # @return [TableProperty] property as defined on table
         
     | 
| 
      
 264 
     | 
    
         
            +
                  #
         
     | 
| 
       103 
265 
     | 
    
         
             
                  def property(name)
         
     | 
| 
       104 
266 
     | 
    
         
             
                    @properties[name].try(:value)
         
     | 
| 
       105 
267 
     | 
    
         
             
                  end
         
     | 
| 
       106 
268 
     | 
    
         | 
| 
      
 269 
     | 
    
         
            +
                  #
         
     | 
| 
      
 270 
     | 
    
         
            +
                  # @return [Boolean] `true` if this table uses compact storage
         
     | 
| 
      
 271 
     | 
    
         
            +
                  #
         
     | 
| 
       107 
272 
     | 
    
         
             
                  def compact_storage?
         
     | 
| 
       108 
273 
     | 
    
         
             
                    !!@compact_storage
         
     | 
| 
       109 
274 
     | 
    
         
             
                  end
         
     | 
| 
       110 
275 
     | 
    
         | 
| 
       111 
276 
     | 
    
         
             
                  protected
         
     | 
| 
      
 277 
     | 
    
         
            +
             
     | 
| 
       112 
278 
     | 
    
         
             
                  attr_reader :columns_by_name
         
     | 
| 
       113 
279 
     | 
    
         | 
| 
       114 
280 
     | 
    
         
             
                  private
         
     | 
| 
         @@ -121,9 +287,6 @@ module Cequel 
     | 
|
| 
       121 
287 
     | 
    
         
             
                  def type(type)
         
     | 
| 
       122 
288 
     | 
    
         
             
                    ::Cequel::Type[type]
         
     | 
| 
       123 
289 
     | 
    
         
             
                  end
         
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
290 
     | 
    
         
             
                end
         
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
291 
     | 
    
         
             
              end
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
292 
     | 
    
         
             
            end
         
     |