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.
- checksums.yaml +4 -4
- data/bin/cassie +8 -181
- data/lib/cassie/configuration/core.rb +26 -3
- data/lib/cassie/configuration/generator.rb +1 -0
- data/lib/cassie/configuration/loading.rb +5 -2
- data/lib/cassie/configuration.rb +1 -0
- data/lib/cassie/connection.rb +13 -7
- data/lib/cassie/connection_handler/README.md +13 -3
- data/lib/cassie/connection_handler/cluster.rb +11 -0
- data/lib/cassie/connection_handler/sessions.rb +9 -0
- data/lib/cassie/connection_handler.rb +8 -7
- data/lib/cassie/definition.rb +28 -0
- data/lib/cassie/extensions/object/color_methods.rb +21 -0
- data/lib/cassie/instrumentation.rb +4 -0
- data/lib/cassie/modification.rb +29 -0
- data/lib/cassie/query.rb +27 -0
- data/lib/cassie/schema/README.md +306 -0
- data/lib/cassie/schema/apply_command.rb +24 -0
- data/lib/cassie/schema/cassandra_migrations/importer.rb +91 -0
- data/lib/cassie/schema/cassandra_migrations/migration_file.rb +51 -0
- data/lib/cassie/schema/configuration.rb +35 -0
- data/lib/cassie/schema/migration/cassandra_support.rb +34 -0
- data/lib/cassie/schema/migration/dsl/announcing.rb +47 -0
- data/lib/cassie/schema/migration/dsl/column_operations.rb +42 -0
- data/lib/cassie/schema/migration/dsl/table_definition.rb +299 -0
- data/lib/cassie/schema/migration/dsl/table_operations.rb +64 -0
- data/lib/cassie/schema/migration/dsl.rb +17 -0
- data/lib/cassie/schema/migration.rb +12 -0
- data/lib/cassie/schema/migrator.rb +115 -0
- data/lib/cassie/schema/queries/create_keyspace_query.rb +26 -0
- data/lib/cassie/{migration → schema}/queries/create_versions_table_query.rb +6 -6
- data/lib/cassie/schema/queries/delete_version_query.rb +17 -0
- data/lib/cassie/schema/queries/drop_keyspace_query.rb +14 -0
- data/lib/cassie/schema/queries/insert_version_query.rb +22 -0
- data/lib/cassie/schema/queries/select_versions_query.rb +18 -0
- data/lib/cassie/{migration → schema}/queries.rb +4 -2
- data/lib/cassie/schema/rollback_command.rb +24 -0
- data/lib/cassie/schema/structure_dumper.rb +117 -0
- data/lib/cassie/{migration → schema}/structure_loader.rb +3 -3
- data/lib/cassie/schema/version.rb +143 -0
- data/lib/cassie/schema/version_file_loader.rb +34 -0
- data/lib/cassie/schema/version_loader.rb +31 -0
- data/lib/cassie/schema/version_object_loader.rb +19 -0
- data/lib/cassie/schema/version_writer.rb +108 -0
- data/lib/cassie/schema/versioning.rb +162 -0
- data/lib/cassie/schema.rb +24 -0
- data/lib/cassie/statements/README.md +61 -9
- data/lib/cassie/statements/core.rb +16 -5
- data/lib/cassie/statements/execution/results/core.rb +1 -1
- data/lib/cassie/statements/execution/results/modification_result.rb +1 -1
- data/lib/cassie/statements/execution/results/query_result.rb +1 -1
- data/lib/cassie/statements/execution.rb +40 -13
- data/lib/cassie/statements/statement/assignments.rb +33 -3
- data/lib/cassie/statements/statement/conditions.rb +3 -1
- data/lib/cassie/statements/statement/deleting.rb +27 -19
- data/lib/cassie/statements/statement/idempotency.rb +23 -4
- data/lib/cassie/statements/statement/inserting.rb +17 -10
- data/lib/cassie/statements/statement/limiting.rb +5 -2
- data/lib/cassie/statements/statement/mapping.rb +34 -6
- data/lib/cassie/statements/statement/preparation/cache.rb +1 -1
- data/lib/cassie/statements/statement/preparation.rb +37 -7
- data/lib/cassie/statements/statement/relations.rb +29 -8
- data/lib/cassie/statements/statement/selection.rb +51 -15
- data/lib/cassie/statements/statement/type_hinting.rb +12 -4
- data/lib/cassie/statements/statement/updating.rb +22 -8
- data/lib/cassie/statements/statement.rb +39 -14
- data/lib/cassie/statements.rb +12 -0
- data/lib/cassie/support/server_process.rb +117 -0
- data/lib/cassie/support/statement_parser.rb +3 -5
- data/lib/cassie/support/{command_runner.rb → system_command.rb} +22 -13
- data/lib/cassie/support.rb +3 -1
- data/lib/cassie/tasks/configuration/generate.rake +35 -0
- data/lib/cassie/tasks/io.rb +15 -0
- data/lib/cassie/tasks/migration/create.rake +49 -0
- data/lib/cassie/tasks/migration/import.rake +39 -0
- data/lib/cassie/tasks/migration/reset.rake +9 -0
- data/lib/cassie/tasks/restart.rake +5 -0
- data/lib/cassie/tasks/schema/drop.rake +28 -0
- data/lib/cassie/tasks/schema/dump.rake +21 -0
- data/lib/cassie/tasks/schema/history.rake +18 -0
- data/lib/cassie/tasks/schema/import.rake +40 -0
- data/lib/cassie/tasks/schema/init.rake +54 -0
- data/lib/cassie/tasks/schema/load.rake +19 -0
- data/lib/cassie/tasks/schema/migrate.rake +42 -0
- data/lib/cassie/tasks/schema/reset.rake +6 -0
- data/lib/cassie/tasks/schema/status.rake +19 -0
- data/lib/cassie/tasks/schema/version.rake +18 -0
- data/lib/cassie/tasks/schema/version_display.rb +50 -0
- data/lib/cassie/tasks/start.rake +17 -0
- data/lib/cassie/tasks/stop.rake +33 -0
- data/lib/cassie/tasks/tail.rake +14 -0
- data/lib/cassie/tasks/task_runner.rb +49 -0
- data/lib/cassie/tasks.rb +18 -0
- data/lib/cassie/testing/fake/execution_info.rb +1 -1
- data/lib/cassie/testing/fake/result.rb +3 -3
- data/lib/cassie/testing.rb +4 -0
- data/lib/cassie/version.rb +1 -1
- data/lib/cassie.rb +4 -1
- metadata +73 -17
- data/lib/cassie/migration/README.md +0 -141
- data/lib/cassie/migration/configuration.rb +0 -18
- data/lib/cassie/migration/initialization.rb +0 -70
- data/lib/cassie/migration/queries/create_schema_keyspace_query.rb +0 -17
- data/lib/cassie/migration/queries/insert_version_query.rb +0 -23
- data/lib/cassie/migration/queries/select_versions_query.rb +0 -14
- data/lib/cassie/migration/structure_dumper.rb +0 -94
- data/lib/cassie/migration/version.rb +0 -4
- 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
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
#
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
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,
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
#
|
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
|
-
|
20
|
-
|
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 =
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
#
|
37
|
-
#
|
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
|
-
#
|
43
|
-
#
|
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
|
data/lib/cassie/statements.rb
CHANGED
@@ -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
|
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
|