cassie 1.0.0.beta.33 → 1.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cassie +8 -181
  3. data/lib/cassie/configuration/core.rb +26 -3
  4. data/lib/cassie/configuration/generator.rb +1 -0
  5. data/lib/cassie/configuration/loading.rb +5 -2
  6. data/lib/cassie/configuration.rb +1 -0
  7. data/lib/cassie/connection.rb +13 -7
  8. data/lib/cassie/connection_handler/README.md +13 -3
  9. data/lib/cassie/connection_handler/cluster.rb +11 -0
  10. data/lib/cassie/connection_handler/sessions.rb +9 -0
  11. data/lib/cassie/connection_handler.rb +8 -7
  12. data/lib/cassie/definition.rb +28 -0
  13. data/lib/cassie/extensions/object/color_methods.rb +21 -0
  14. data/lib/cassie/instrumentation.rb +4 -0
  15. data/lib/cassie/modification.rb +29 -0
  16. data/lib/cassie/query.rb +27 -0
  17. data/lib/cassie/schema/README.md +306 -0
  18. data/lib/cassie/schema/apply_command.rb +24 -0
  19. data/lib/cassie/schema/cassandra_migrations/importer.rb +91 -0
  20. data/lib/cassie/schema/cassandra_migrations/migration_file.rb +51 -0
  21. data/lib/cassie/schema/configuration.rb +35 -0
  22. data/lib/cassie/schema/migration/cassandra_support.rb +34 -0
  23. data/lib/cassie/schema/migration/dsl/announcing.rb +47 -0
  24. data/lib/cassie/schema/migration/dsl/column_operations.rb +42 -0
  25. data/lib/cassie/schema/migration/dsl/table_definition.rb +299 -0
  26. data/lib/cassie/schema/migration/dsl/table_operations.rb +64 -0
  27. data/lib/cassie/schema/migration/dsl.rb +17 -0
  28. data/lib/cassie/schema/migration.rb +12 -0
  29. data/lib/cassie/schema/migrator.rb +115 -0
  30. data/lib/cassie/schema/queries/create_keyspace_query.rb +26 -0
  31. data/lib/cassie/{migration → schema}/queries/create_versions_table_query.rb +6 -6
  32. data/lib/cassie/schema/queries/delete_version_query.rb +17 -0
  33. data/lib/cassie/schema/queries/drop_keyspace_query.rb +14 -0
  34. data/lib/cassie/schema/queries/insert_version_query.rb +22 -0
  35. data/lib/cassie/schema/queries/select_versions_query.rb +18 -0
  36. data/lib/cassie/{migration → schema}/queries.rb +4 -2
  37. data/lib/cassie/schema/rollback_command.rb +24 -0
  38. data/lib/cassie/schema/structure_dumper.rb +117 -0
  39. data/lib/cassie/{migration → schema}/structure_loader.rb +3 -3
  40. data/lib/cassie/schema/version.rb +143 -0
  41. data/lib/cassie/schema/version_file_loader.rb +34 -0
  42. data/lib/cassie/schema/version_loader.rb +31 -0
  43. data/lib/cassie/schema/version_object_loader.rb +19 -0
  44. data/lib/cassie/schema/version_writer.rb +108 -0
  45. data/lib/cassie/schema/versioning.rb +162 -0
  46. data/lib/cassie/schema.rb +24 -0
  47. data/lib/cassie/statements/README.md +61 -9
  48. data/lib/cassie/statements/core.rb +16 -5
  49. data/lib/cassie/statements/execution/results/core.rb +1 -1
  50. data/lib/cassie/statements/execution/results/modification_result.rb +1 -1
  51. data/lib/cassie/statements/execution/results/query_result.rb +1 -1
  52. data/lib/cassie/statements/execution.rb +40 -13
  53. data/lib/cassie/statements/statement/assignments.rb +33 -3
  54. data/lib/cassie/statements/statement/conditions.rb +3 -1
  55. data/lib/cassie/statements/statement/deleting.rb +27 -19
  56. data/lib/cassie/statements/statement/idempotency.rb +23 -4
  57. data/lib/cassie/statements/statement/inserting.rb +17 -10
  58. data/lib/cassie/statements/statement/limiting.rb +5 -2
  59. data/lib/cassie/statements/statement/mapping.rb +34 -6
  60. data/lib/cassie/statements/statement/preparation/cache.rb +1 -1
  61. data/lib/cassie/statements/statement/preparation.rb +37 -7
  62. data/lib/cassie/statements/statement/relations.rb +29 -8
  63. data/lib/cassie/statements/statement/selection.rb +51 -15
  64. data/lib/cassie/statements/statement/type_hinting.rb +12 -4
  65. data/lib/cassie/statements/statement/updating.rb +22 -8
  66. data/lib/cassie/statements/statement.rb +39 -14
  67. data/lib/cassie/statements.rb +12 -0
  68. data/lib/cassie/support/server_process.rb +117 -0
  69. data/lib/cassie/support/statement_parser.rb +3 -5
  70. data/lib/cassie/support/{command_runner.rb → system_command.rb} +22 -13
  71. data/lib/cassie/support.rb +3 -1
  72. data/lib/cassie/tasks/configuration/generate.rake +35 -0
  73. data/lib/cassie/tasks/io.rb +15 -0
  74. data/lib/cassie/tasks/migration/create.rake +49 -0
  75. data/lib/cassie/tasks/migration/import.rake +39 -0
  76. data/lib/cassie/tasks/migration/reset.rake +9 -0
  77. data/lib/cassie/tasks/restart.rake +5 -0
  78. data/lib/cassie/tasks/schema/drop.rake +28 -0
  79. data/lib/cassie/tasks/schema/dump.rake +21 -0
  80. data/lib/cassie/tasks/schema/history.rake +18 -0
  81. data/lib/cassie/tasks/schema/import.rake +40 -0
  82. data/lib/cassie/tasks/schema/init.rake +54 -0
  83. data/lib/cassie/tasks/schema/load.rake +19 -0
  84. data/lib/cassie/tasks/schema/migrate.rake +42 -0
  85. data/lib/cassie/tasks/schema/reset.rake +6 -0
  86. data/lib/cassie/tasks/schema/status.rake +19 -0
  87. data/lib/cassie/tasks/schema/version.rake +18 -0
  88. data/lib/cassie/tasks/schema/version_display.rb +50 -0
  89. data/lib/cassie/tasks/start.rake +17 -0
  90. data/lib/cassie/tasks/stop.rake +33 -0
  91. data/lib/cassie/tasks/tail.rake +14 -0
  92. data/lib/cassie/tasks/task_runner.rb +49 -0
  93. data/lib/cassie/tasks.rb +18 -0
  94. data/lib/cassie/testing/fake/execution_info.rb +1 -1
  95. data/lib/cassie/testing/fake/result.rb +3 -3
  96. data/lib/cassie/testing.rb +4 -0
  97. data/lib/cassie/version.rb +1 -1
  98. data/lib/cassie.rb +4 -1
  99. metadata +73 -17
  100. data/lib/cassie/migration/README.md +0 -141
  101. data/lib/cassie/migration/configuration.rb +0 -18
  102. data/lib/cassie/migration/initialization.rb +0 -70
  103. data/lib/cassie/migration/queries/create_schema_keyspace_query.rb +0 -17
  104. data/lib/cassie/migration/queries/insert_version_query.rb +0 -23
  105. data/lib/cassie/migration/queries/select_versions_query.rb +0 -14
  106. data/lib/cassie/migration/structure_dumper.rb +0 -94
  107. data/lib/cassie/migration/version.rb +0 -4
  108. data/lib/cassie/migration.rb +0 -30
@@ -1,15 +1,43 @@
1
1
  module Cassie::Statements::Statement
2
2
  module Mapping
3
- extend ActiveSupport::Concern
4
3
 
5
- included do
6
- # We are mapping term values from a client provided resource.
7
- # store this object in `_resource` attribte
8
- # as they could reasonably want to name it `resource`
9
- attr_accessor :_resource
4
+ def self.included(base)
5
+ base.instance_eval do
6
+ # We are mapping term values from a client provided resource.
7
+ # store this object in `_resource` attribte
8
+ # as they could reasonably want to name it `resource`
9
+ attr_accessor :_resource
10
+ end
11
+ base.extend ClassMethods
10
12
  end
11
13
 
14
+ # @!parse extend ClassMethods
12
15
  module ClassMethods
16
+ # DSL setting a getter and setter.
17
+ #
18
+ # When use with a relation (+where+) or assignment (+set+),
19
+ # the fetching of column values are
20
+ # delegated to the object in this getter.
21
+ #
22
+ # @note This delegation behavor gets last preference.
23
+ # * An overwritten +column_name+ getter has first preference
24
+ # * the +@column_name+ instance variable has next preference
25
+ # * the mapped resource delegation has last preference
26
+ #
27
+ # @example Simple Mapping delegation
28
+ # Class Statement
29
+ # include Cassie::Statements::Statement:Relations
30
+ # include Cassie::Statements::Statement:Mapping
31
+ #
32
+ # where :name
33
+ #
34
+ # map_from :user
35
+ # end
36
+ #
37
+ # s = Statement.new
38
+ # s.user = User.new(id: 1)
39
+ # s.id
40
+ # #=> 1
13
41
  def map_from(resource_name)
14
42
  define_method resource_name do
15
43
  _resource
@@ -43,7 +43,7 @@ module Cassie::Statements::Statement
43
43
  def self.init_cache
44
44
  previous_cache = defined?(@cache) ? @cache : nil
45
45
 
46
- #TODO: research why memory story is blowing up when
46
+ # @todo research why memory story is blowing up when
47
47
  # serializing the Cassandra prepared statement result
48
48
  # @cache = ActiveSupport::Cache::MemoryStore.new
49
49
  @cache = Cache.new
@@ -1,27 +1,57 @@
1
1
  require_relative 'preparation/cache'
2
2
 
3
3
  module Cassie::Statements::Statement
4
+ # Sepcific functionality and DSL for prepared statements.
5
+ #
6
+ # When included, a local, in-memory statement cache will be used
7
+ # when generating the statement object if +prepared?+ is +true+.
8
+ #
9
+ # By default, {.prepare} defaults to +true+, since most statements should be prepared.
10
+ #
11
+ # The cache key is the +cql+ for the statment, or the statement itself
12
+ # if it does not respond to +cql+. For bound statments (recommended)
13
+ # this results in only cacheing once per unique statement type, independent
14
+ # of the values for a particular statemtn (which are in the +params+ attribute, not the +cql+ attribute).
15
+ #
16
+ # The following class attributes are affected when included:
17
+ # * Sets {.prepared} to +true+ since most statements should be prepared.
4
18
  module Preparation
5
- extend ::ActiveSupport::Concern
6
-
7
- included do
8
- class << self
9
- attr_accessor :prepare
19
+ # @!visibility private
20
+ def self.included(base)
21
+ base.extend ClassMethods
22
+ base.instance_eval do
23
+ self.prepare = true
10
24
  end
11
- self.prepare = true
12
25
  end
13
26
 
27
+ # @!parse extend ClassMethods
14
28
  module ClassMethods
29
+
30
+ #@!visibility private
15
31
  def inherited(subclass)
16
32
  subclass.prepare = prepare
17
33
  super
18
34
  end
19
35
 
36
+ # @return [Boolean] whether the statement will be prepared when executed
37
+ def prepare
38
+ @prepare
39
+ end
40
+
41
+ def prepare=(val)
42
+ @prepare = !!val
43
+ end
44
+
45
+ # @return [Boolean] indicating whether the statement will be prepared when executed
20
46
  def prepare?
21
47
  !!prepare
22
48
  end
23
49
  end
24
50
 
51
+ # override. The statement object, fetched from perpared statements
52
+ # cache if {#prepare?} is +true+
53
+ # @return [Cassandra::Statements::Prepared, Object] A bound,
54
+ # prepared statement if {#prepare?} is +true+, otherwise +super+
25
55
  def statement
26
56
  statement = super
27
57
  if self.class.prepare?
@@ -37,7 +67,7 @@ module Cassie::Statements::Statement
37
67
  end
38
68
  end
39
69
 
40
- private
70
+ protected
41
71
 
42
72
  def statement_cache
43
73
  Cassie::Statements::Statement::Preparation.cache
@@ -20,30 +20,51 @@ module Cassie::Statements::Statement
20
20
  extend ActiveSupport::Concern
21
21
 
22
22
  module ClassMethods
23
- # where :username, :eq, value: :method
24
- # where :phone, :in
25
- # relation :user_id, :gteq, term: "minTimeuuid('2013-02-02 10:00+0000')"
26
- def where(identifier, op, opts={})
27
- opts[:value] ||= implied_argument_method(identifier, op)
23
+ # DSL to set a ranging relation (+WHERE+ clause) for the statement.
24
+ #
25
+ # Defining a relation also defines an +attr_accessor+ with the same name as
26
+ # the identifier (or the +:value+ option if a symbol is used). The underlying instance
27
+ # variable value for this accessor will be used when determining the value for the relation.
28
+ #
29
+ # @param [String, Symbol] identifier The field name or other CQL identifier to restrict the query.
30
+ # @param [Symbol] operation Which operation to use. See {Cassie::Statements::Statement::Relation::OPERATIONS} for valid symbols and their associated operations.
31
+ # @param [Hash] opts options for the relation
32
+ # @option opts [Symbol, Object] :value The value to use for the ranging relation (constraint). If a [Symbol], a method with that name will be called when the statement is built. Otherwise, the value itself will be used.
33
+ # @option opts [Symbol, Object] :if Determines if the relation is applied to the statement or not. If a [Symbol], a method with that name will be called when the statement is built. Otherwise, the value itself will be used.
34
+ # @option opts [String] :term The argument value to use instead of a positional placeholder (?). If a [Symbol], a method with that name will be called when the statement is built. Otherwise, the value itself will be used.
35
+ # @return [Enumerable<Array<Object>>] The enumeration of current relations' parameters
36
+ # @raise [StandardError] if there is already a getter or setter method defined for the
37
+ # relation value's implied accessor (+identifier+ or symbol +:value+ option).
38
+ #
39
+ # @example Range relation with implied accessor
40
+ # where :username, :eq #<= gets relation value from `:username` method
41
+ # @example Range relation with explicit accessor
42
+ # where :username, :eq, value: :name #<= gets relation value from `:name` method
43
+ # @example Range relation with multi-value, pluarlized accessr
44
+ # where :phone, :in #<= gets relation value from `:phones` method
45
+ def where(identifier, operation, opts={})
46
+ opts[:value] ||= implied_argument_method(identifier, operation)
28
47
 
29
48
  define_argument_accessor(opts[:value])
30
49
 
31
- relations_args << [identifier, op, opts.delete(:value), opts]
50
+ relations_args << [identifier, operation, opts.delete(:value), opts]
32
51
  end
33
52
 
53
+ # The enumeration of current relations' parameters that will be
54
+ # used to build Relation objects when the statement is built
34
55
  def relations_args
35
56
  @relations_args ||= []
36
57
  end
37
58
 
38
59
  protected
39
60
 
40
- #TODO: extract argument accessor creation for
61
+ # @todo extract argument accessor creation for
41
62
  # more DRY and clear usage. See mapping module.
42
63
  def define_argument_accessor(name)
43
64
  unless Symbol === name
44
65
  raise ArgumentError, "A Symbol is required for the accessor methods for setting/getting a relation's value. #{name.class} (#{name}) given."
45
66
  end
46
- #TODO: this should probably only raise
67
+ # @todo this should probably only raise
47
68
  # if value option was nil and we
48
69
  # are implicilty creating getter/setters.
49
70
  if method_defined?(name) || method_defined?("#{name}=")
@@ -5,21 +5,42 @@ require_relative 'relations'
5
5
  require_relative 'ordering'
6
6
 
7
7
  module Cassie::Statements::Statement
8
+ # Sepcific functionality and DSL for selection statements
9
+ #
10
+ # The following class attributes are affected when included:
11
+ # * Sets {.idempotent} to +true+ since selection queries are idempotent by definition.
12
+ # * Sets the {.result_class} to {Cassie::Statements::Results::QueryResult}
8
13
  module Selection
9
- extend ::ActiveSupport::Concern
10
14
 
11
- included do
12
- include Relations
13
- include Ordering
14
- include Limiting
15
- include AllowFiltering
16
- include Pagination
17
-
18
- @result_class = Cassie::Statements::Results::QueryResult
19
- @idempotent = true
15
+ # @!visibility private
16
+ # @!parse include Relations
17
+ # @!parse extend Relations::ClassMethods
18
+ # @!parse include Ordering
19
+ # @!parse extend Ordering::ClassMethods
20
+ # @!parse include Limiting
21
+ # @!parse extend Limiting::ClassMethods
22
+ # @!parse include AllowFiltering
23
+ # @!parse extend AllowFiltering::ClassMethods
24
+ # @!parse include Pagination
25
+ # @!parse extend Pagination::ClassMethods
26
+ def self.included(base)
27
+ base.instance_eval do
28
+ include Relations
29
+ include Ordering
30
+ include Limiting
31
+ include AllowFiltering
32
+ include Pagination
33
+
34
+ @result_class = Cassie::Statements::Results::QueryResult
35
+ @idempotent = true
36
+ end
37
+ base.extend ClassMethods
20
38
  end
21
39
 
22
40
  module ClassMethods
41
+ # DSL to set the statement type and table for selection
42
+ # @param [String, Symbol] table The table to taret for the select statement
43
+ # @return [void]
23
44
  def select_from(table)
24
45
  self.table = table
25
46
  self.type = :select
@@ -27,26 +48,41 @@ module Cassie::Statements::Statement
27
48
  yield(self) if block_given?
28
49
  end
29
50
 
30
- def select(selector, opts={})
31
- selector = selector.to_s
32
- selector += " AS #{opts[:as]}" if opts[:as]
33
- selectors << selector
51
+ # DSL to add a column to be ruturned for each row in the query results
52
+ # @param [String, Symbol] column The column name in the CQL schmea to return
53
+ # @param [Hash] opts options for the selector
54
+ # @option opts [String] :as The identifier to use for the field when returned in the result if different than the column name
55
+ # @return [String] the current enumeration of selectors
56
+ def select(column, opts={})
57
+ column = column.to_s
58
+ column += " AS #{opts[:as]}" if opts[:as]
59
+ selectors << column
34
60
  end
35
61
 
36
- # a select clause is built up of selectors
62
+ # The enumeration of selectors for use in the statement
63
+ # @return [Array<String>]
37
64
  def selectors
38
65
  @selectors ||= []
39
66
  end
40
67
 
68
+ # DSL to wrap a selector in the +WRITETIME+ CQL,
69
+ # used to select the time the field was written
70
+ # instead of the value itself
41
71
  def write_time(selector)
42
72
  "WRITETIME(#{selector})"
43
73
  end
44
74
  alias writetime write_time
45
75
 
76
+ # DSL to wrap a selector in the +TTL+ CQL,
77
+ # used to select the time until the field will be
78
+ # tombstoned, instead of the value itself
46
79
  def ttl(selector)
47
80
  "TTL(#{selector})"
48
81
  end
49
82
 
83
+ # DSL to wrap a selector in the +COUNT+ CQL,
84
+ # used to select the aggregation of the number of rows
85
+ # instead of the value in each row
50
86
  def count(selector='*')
51
87
  "COUNT(#{selector})"
52
88
  end
@@ -1,4 +1,4 @@
1
- module Cassie::Statements
1
+ module Cassie::Statements
2
2
  module Statement::TypeHinting
3
3
  extend ActiveSupport::Concern
4
4
 
@@ -7,6 +7,7 @@ module Cassie::Statements
7
7
  end
8
8
 
9
9
  module ClassMethods
10
+ # @!visibility private
10
11
  def inherited(subclass)
11
12
  subclass.type_hints = type_hints if defined?(@type_hints)
12
13
  super
@@ -16,16 +17,23 @@ module Cassie::Statements
16
17
  @type_hints = val
17
18
  end
18
19
 
19
- def type_hints(val=:get)
20
- if val == :get
20
+ # DSL to set the type hints execution option
21
+ # Defaults to +nil+ if none are set
22
+ # @param [Array, Hash] hints Hints to use for value serialization. Array for positional arguments, Hash for named arguments.
23
+ # @return [Array, Hash] hints to use for value serialization. Array for positional arguments, Hash for named arguments.
24
+ def type_hints(hints=:get)
25
+ if hints == :get
21
26
  return @type_hints if defined?(@type_hints)
22
27
  nil
23
28
  else
24
- self.type_hints = val
29
+ self.type_hints = hints
25
30
  end
26
31
  end
27
32
  end
28
33
 
34
+ # The type hints for this object's statement
35
+ # Defaults to {.type_hints} if none are set on the object
36
+ # @return [Array, Hash] hints to use for value serialization. Array for positional arguments, Hash for named arguments.
29
37
  def type_hints
30
38
  return @type_hints if defined?(@type_hints)
31
39
  self.class.type_hints
@@ -3,17 +3,30 @@ require_relative 'conditions'
3
3
 
4
4
  module Cassie::Statements::Statement
5
5
  module Updating
6
- extend ::ActiveSupport::Concern
7
6
 
8
- included do
9
- include Relations
10
- include Assignments
11
- include Conditions
12
-
13
- @result_class = Cassie::Statements::Results::ModificationResult
7
+ # @!visibility private
8
+ # @!parse include Relations
9
+ # @!parse extend Relations::ClassMethods
10
+ # @!parse include Assignments
11
+ # @!parse extend Assignments::ClassMethods
12
+ # @!parse include Conditions
13
+ # @!parse extend Conditions::ClassMethods
14
+ def self.included(base)
15
+ base.instance_eval do
16
+ include Relations
17
+ include Assignments
18
+ include Conditions
19
+
20
+ @result_class = Cassie::Statements::Results::ModificationResult
21
+ end
22
+ base.extend ClassMethods
14
23
  end
15
24
 
25
+ # @!parse extend ClassMethods
16
26
  module ClassMethods
27
+ # DSL to set the statement type and table for updating
28
+ # @param [String, Symbol] table The table to taret for the update statement
29
+ # @return [void]
17
30
  def update(table)
18
31
  self.table = table
19
32
  self.type = :update
@@ -23,7 +36,8 @@ module Cassie::Statements::Statement
23
36
  end
24
37
 
25
38
  protected
26
-
39
+ # Sets the {#cql} and {#params} for a building a bound statement
40
+ # @return [void]
27
41
  def build_update_cql_and_params
28
42
  assignment_str, update_params = build_update_and_params
29
43
  where_str, where_params = build_where_and_params
@@ -16,16 +16,23 @@ module Cassie::Statements
16
16
 
17
17
  class Invalid < StandardError; end
18
18
 
19
- extend ::ActiveSupport::Concern
20
-
21
- included do
22
- include Preparation
23
- include TypeHinting
24
- include Idempotency
25
-
26
- class << self
27
- attr_accessor :table
28
- attr_accessor :type
19
+ # @!visibility private
20
+ # @!parse include Preparation
21
+ # @!parse extend Preparation::ClassMethods
22
+ # @!parse include TypeHinting
23
+ # @!parse include TypeHinting::ClassMethods
24
+ # @!parse include Idempotency
25
+ # @!parse include Idempotency::ClassMethods
26
+ def self.included(base)
27
+ base.instance_eval do
28
+ include Preparation
29
+ include TypeHinting
30
+ include Idempotency
31
+
32
+ class << self
33
+ attr_accessor :table
34
+ attr_accessor :type
35
+ end
29
36
  end
30
37
  end
31
38
 
@@ -33,14 +40,22 @@ module Cassie::Statements
33
40
  self.class.table
34
41
  end
35
42
 
36
- # returns a CQL string, or a Cassandra::Statement
37
- # that is ready for execution
43
+ # A bound statment with type hint and idempotent options, ready for execution ready for execution with a [Cassandra::Session]
44
+ # @return [Cassandra::Statement]
38
45
  def statement
39
46
  Cassandra::Statements::Simple.new(*build_cql_and_params, type_hints, idempotent?)
40
47
  end
41
48
 
42
- # returns a CQL string with inline parameters, that
43
- # is representative of what could be executed in a CQL shell
49
+ # A CQL string with inline parameters, representing the current statement
50
+ # as it would be executed in a CQL shell
51
+ #
52
+ # @note This CQL string does not include execution options like type hinting,
53
+ # idempotency, consistency level, etc -- just the raw CQL instruction and values.
54
+ # @return [String]
55
+ #
56
+ # @example
57
+ # statement.to_cql
58
+ # #=> "SELECT * FROM table WHERE first='evan' AND middle='thomas' and last='prothro"
44
59
  def to_cql
45
60
  if statement.respond_to?(:cql) && statement.respond_to?(:params)
46
61
  Cassie::Support::StatementParser.new(statement).to_cql
@@ -53,11 +68,21 @@ module Cassie::Statements
53
68
  Cassie::Statements.logger
54
69
  end
55
70
 
71
+ # The CQL string portion for the statment
72
+ # @!parse attr_reader :cql
73
+ # @example
74
+ # statement.cql
75
+ # #=> "SELECT * FROM table WHERE first=? AND middle=? and last=?"
56
76
  def cql
57
77
  return @cql if defined?(@cql)
58
78
  ""
59
79
  end
60
80
 
81
+ # The positional values portion for the statment
82
+ # @example
83
+ # statement.params
84
+ # #=> ['evan', 'thomas', 'prothro']
85
+ # @!parse attr_reader :params
61
86
  def params
62
87
  return @params if defined?(@params)
63
88
  nil
@@ -1,4 +1,16 @@
1
1
  module Cassie
2
+ # Contains components related to Cassandra statements, including
3
+ # * building with a CQL DSL
4
+ # * options for executing built statements
5
+ # * executing built statements
6
+ # * instrumenting
7
+ # * logging (using instrumentation)
8
+ #
9
+ # See +Statements+ submodules for more information on the responsibilities of
10
+ # these individual components.
11
+ #
12
+ # See {Cassie::Query}, {Cassie::Modification} or {Cassie::Definition}
13
+ # to see concrete query interfaces implementeing these components.
2
14
  module Statements
3
15
  require_relative 'statements/core'
4
16
  require_relative 'statements/query'
@@ -0,0 +1,117 @@
1
+ module Cassie
2
+ module Support
3
+ class ServerProcess
4
+
5
+ attr_reader :pid
6
+
7
+ # Scan the system for cassandra processes running
8
+ # @return [Array<ServerProcess>] Running cassandra processes
9
+ # @raise [RuntimeError] if scanning with +ps+ system calls fails.
10
+ def self.all
11
+ pids.map{|pid| new(pid)}
12
+ end
13
+
14
+ # The path to the active cassandra binary's log file
15
+ # Does not yet respect a configured log path,
16
+ # and assumes the path is relative to bin/casandra at ../logs/system.log
17
+ # @!parse attr_reader :log_path
18
+ def self.log_path
19
+ which = Cassie::Support::SystemCommand.new("which", ["cassandra"])
20
+ which.succeed
21
+
22
+ bin_path = which.output.tr("\n", '')
23
+ bin_path.sub('bin/cassandra', 'logs/system.log')
24
+ end
25
+
26
+ # Starts a cassandra server process. {#running?} will be true if it started correctly.
27
+ def initialize(pid=nil)
28
+ @pid = pid
29
+
30
+ if pid
31
+ @running = true
32
+ else
33
+ start_cassandra
34
+ end
35
+ end
36
+
37
+ # @return [Boolean] If the cassandra server started correctly. See {#errors} if false.
38
+ def running?
39
+ !!@running
40
+ end
41
+
42
+ # Stops the cassandra server processes, synchronously.
43
+ # @raise [RuntimeError] if the process could not be killed.
44
+ def stop
45
+ self.class.pids.each do|pid|
46
+ Process.kill("TERM", pid)
47
+ loop do
48
+ sleep(0.1)
49
+ begin
50
+ Process.getpgid( pid )
51
+ rescue Errno::ESRCH
52
+ break
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def command
59
+ details[:command]
60
+ end
61
+
62
+ # @return [Array<String>] The Cassandra output lines tagged with ERROR
63
+ # @!parse attr_reader :errors
64
+ def errors
65
+ return [] unless command && command.output
66
+ command.output.split("\n").grep(/ERROR/)
67
+ end
68
+
69
+ protected
70
+
71
+ def self.pids
72
+ ps = Cassie::Support::SystemCommand.new("ps", ["-awx"])
73
+ ps.succeed
74
+ cassandra_awx = ps.output.split("\n").grep(/cassandra/)
75
+ cassandra_awx.map{ |p| p.split(' ').first.to_i }
76
+ end
77
+
78
+ def start_cassandra
79
+ start_pids = self.class.pids
80
+ cassandra = Cassie::Support::SystemCommand.new("cassandra")
81
+ cassandra.run
82
+ new_pids = self.class.pids - start_pids
83
+ Cassie.logger.warn "[WARN] - Multiple cassandra processes started, using first one." if new_pids.length > 1
84
+
85
+ @running = !!(cassandra.output =~ /state jump to NORMAL/)
86
+ @pid = new_pids.first
87
+ end
88
+
89
+ def details
90
+ @details ||= fetch_details
91
+ end
92
+
93
+ def fetch_details
94
+ # http://linuxcommand.org/man_pages/ps1.html (key long descriptions)
95
+ # virtual memory size of the process in KiB
96
+ # ps -p 62027 -o pid,user,ltime,vsize,pcpu,args -ww
97
+ # PID USER TIME VSZ %CPU ARGS
98
+ # 62027 eprothro 44:24 6201356 1.0 /Library/Java/Java
99
+ ps = Cassie::Support::SystemCommand.new("ps", ["-p", pid, "-o", "pid,user,etime,vsize,pcpu,args", "-ww"])
100
+ ps.succeed
101
+ puts ps.output
102
+ elements = ps.output.split("\n")[1]
103
+ elements = elements.split(" ")
104
+ raise "Error fetching details, pid fetched doesn't match pid queried" unless elements.shift.to_i == self.pid
105
+
106
+ {}.tap do |h|
107
+ h[:user] = elements.shift
108
+ offset = Time.now.getlocal.to_s.split(' ').last
109
+ h[:started_at] = DateTime.parse("#{elements.shift} #{offset}")
110
+ h[:memory] = elements.shift * 1024
111
+ h[:cpu] = elements.shift / 100.0
112
+ end
113
+ #{p.split(' ').first.ljust(5,' ')} | #{p.split(' ').last}"
114
+ end
115
+ end
116
+ end
117
+ end
@@ -1,5 +1,7 @@
1
1
  module Cassie::Support
2
2
  class StatementParser
3
+ QUOTED_TYPES = [:date, :time, :text, :timestamp, :inet, :ascii].freeze
4
+
3
5
  attr_reader :statement
4
6
 
5
7
  def initialize(statement)
@@ -24,7 +26,7 @@ module Cassie::Support
24
26
  params_types.map.with_index do |type, i|
25
27
  cassandra_param = type.new(params[i])
26
28
  quoted_val = if QUOTED_TYPES.include? type.kind
27
- "'#{cassandra_param.to_s}'"
29
+ "'#{cassandra_param}'"
28
30
  else
29
31
  cassandra_param.to_s
30
32
  end
@@ -33,9 +35,5 @@ module Cassie::Support
33
35
  end
34
36
  cql
35
37
  end
36
-
37
- protected
38
-
39
- QUOTED_TYPES = [:date, :time, :text, :timestamp, :inet, :ascii].freeze
40
38
  end
41
39
  end