dbagile 0.0.1
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.
- data/LICENCE.textile +12 -0
- data/README.textile +89 -0
- data/bin/dba +22 -0
- data/lib/dbagile/adapter/sequel/class_methods.rb +18 -0
- data/lib/dbagile/adapter/sequel/connection.rb +38 -0
- data/lib/dbagile/adapter/sequel/data/table_driven.rb +30 -0
- data/lib/dbagile/adapter/sequel/data/transaction_driven.rb +43 -0
- data/lib/dbagile/adapter/sequel/schema/concrete_script.rb +135 -0
- data/lib/dbagile/adapter/sequel/schema/physical_dump.rb +106 -0
- data/lib/dbagile/adapter/sequel/schema/schema2sequel_args.rb +71 -0
- data/lib/dbagile/adapter/sequel/schema/table_driven.rb +52 -0
- data/lib/dbagile/adapter/sequel/schema/transaction_driven.rb +46 -0
- data/lib/dbagile/adapter/sequel/sequel_tracer.rb +144 -0
- data/lib/dbagile/adapter/sequel.rb +46 -0
- data/lib/dbagile/adapter.rb +15 -0
- data/lib/dbagile/command/api.rb +49 -0
- data/lib/dbagile/command/bulk/commons.rb +130 -0
- data/lib/dbagile/command/bulk/export.rb +99 -0
- data/lib/dbagile/command/bulk/import.rb +147 -0
- data/lib/dbagile/command/bulk.rb +3 -0
- data/lib/dbagile/command/class_methods.rb +103 -0
- data/lib/dbagile/command/db/add.rb +94 -0
- data/lib/dbagile/command/db/list.rb +40 -0
- data/lib/dbagile/command/db/ping.rb +49 -0
- data/lib/dbagile/command/db/rm.rb +52 -0
- data/lib/dbagile/command/db/stage.rb +81 -0
- data/lib/dbagile/command/db/use.rb +48 -0
- data/lib/dbagile/command/db.rb +6 -0
- data/lib/dbagile/command/dba.rb +121 -0
- data/lib/dbagile/command/help.rb +50 -0
- data/lib/dbagile/command/repo/create.rb +54 -0
- data/lib/dbagile/command/repo.rb +1 -0
- data/lib/dbagile/command/robust.rb +86 -0
- data/lib/dbagile/command/schema/check.rb +59 -0
- data/lib/dbagile/command/schema/commons.rb +118 -0
- data/lib/dbagile/command/schema/diff.rb +101 -0
- data/lib/dbagile/command/schema/dump.rb +48 -0
- data/lib/dbagile/command/schema/merge.rb +55 -0
- data/lib/dbagile/command/schema/sql_script.rb +124 -0
- data/lib/dbagile/command/schema.rb +6 -0
- data/lib/dbagile/command/sql/drop.rb +40 -0
- data/lib/dbagile/command/sql/heading.rb +34 -0
- data/lib/dbagile/command/sql/send.rb +67 -0
- data/lib/dbagile/command/sql/show.rb +42 -0
- data/lib/dbagile/command/sql.rb +4 -0
- data/lib/dbagile/command/web/tools.rb +23 -0
- data/lib/dbagile/command/web.rb +1 -0
- data/lib/dbagile/command.rb +158 -0
- data/lib/dbagile/contract/connection.rb +66 -0
- data/lib/dbagile/contract/data/dataset.rb +69 -0
- data/lib/dbagile/contract/data/table_driven.rb +49 -0
- data/lib/dbagile/contract/data/transaction_driven.rb +74 -0
- data/lib/dbagile/contract/data.rb +3 -0
- data/lib/dbagile/contract/robust/helpers.rb +19 -0
- data/lib/dbagile/contract/robust/optimistic/data/table_driven.rb +31 -0
- data/lib/dbagile/contract/robust/optimistic/data/transaction_driven.rb +45 -0
- data/lib/dbagile/contract/robust/optimistic/schema/table_driven.rb +53 -0
- data/lib/dbagile/contract/robust/optimistic/schema/transaction_driven.rb +45 -0
- data/lib/dbagile/contract/robust/optimistic.rb +18 -0
- data/lib/dbagile/contract/robust.rb +20 -0
- data/lib/dbagile/contract/schema/table_driven.rb +89 -0
- data/lib/dbagile/contract/schema/transaction_driven.rb +68 -0
- data/lib/dbagile/contract/schema.rb +2 -0
- data/lib/dbagile/contract/utils/delegate.rb +17 -0
- data/lib/dbagile/contract/utils/full.rb +13 -0
- data/lib/dbagile/contract/utils.rb +2 -0
- data/lib/dbagile/contract.rb +5 -0
- data/lib/dbagile/core/chain.rb +92 -0
- data/lib/dbagile/core/connection.rb +51 -0
- data/lib/dbagile/core/database.rb +221 -0
- data/lib/dbagile/core/io/dsl.rb +95 -0
- data/lib/dbagile/core/io/robustness.rb +82 -0
- data/lib/dbagile/core/io.rb +2 -0
- data/lib/dbagile/core/repository/builder.rb +67 -0
- data/lib/dbagile/core/repository/yaml_methods.rb +82 -0
- data/lib/dbagile/core/repository.rb +211 -0
- data/lib/dbagile/core/schema/builder/coercion.rb +210 -0
- data/lib/dbagile/core/schema/builder/concept_factory.rb +61 -0
- data/lib/dbagile/core/schema/builder.rb +187 -0
- data/lib/dbagile/core/schema/composite.rb +239 -0
- data/lib/dbagile/core/schema/computations/filter.rb +40 -0
- data/lib/dbagile/core/schema/computations/merge.rb +55 -0
- data/lib/dbagile/core/schema/computations/minus.rb +44 -0
- data/lib/dbagile/core/schema/computations/split.rb +37 -0
- data/lib/dbagile/core/schema/computations.rb +4 -0
- data/lib/dbagile/core/schema/database_schema.rb +129 -0
- data/lib/dbagile/core/schema/errors.rb +173 -0
- data/lib/dbagile/core/schema/logical/attribute.rb +68 -0
- data/lib/dbagile/core/schema/logical/constraint/candidate_key.rb +70 -0
- data/lib/dbagile/core/schema/logical/constraint/foreign_key.rb +121 -0
- data/lib/dbagile/core/schema/logical/constraint.rb +58 -0
- data/lib/dbagile/core/schema/logical/constraints.rb +28 -0
- data/lib/dbagile/core/schema/logical/heading.rb +47 -0
- data/lib/dbagile/core/schema/logical/relvar.rb +81 -0
- data/lib/dbagile/core/schema/logical.rb +24 -0
- data/lib/dbagile/core/schema/migrate/abstract_script.rb +35 -0
- data/lib/dbagile/core/schema/migrate/collapse_table.rb +15 -0
- data/lib/dbagile/core/schema/migrate/create_table.rb +15 -0
- data/lib/dbagile/core/schema/migrate/drop_table.rb +15 -0
- data/lib/dbagile/core/schema/migrate/expand_table.rb +15 -0
- data/lib/dbagile/core/schema/migrate/operation.rb +141 -0
- data/lib/dbagile/core/schema/migrate/stager.rb +282 -0
- data/lib/dbagile/core/schema/migrate.rb +2 -0
- data/lib/dbagile/core/schema/part.rb +114 -0
- data/lib/dbagile/core/schema/physical/index.rb +64 -0
- data/lib/dbagile/core/schema/physical/indexes.rb +12 -0
- data/lib/dbagile/core/schema/physical.rb +26 -0
- data/lib/dbagile/core/schema/robustness.rb +39 -0
- data/lib/dbagile/core/schema/schema_object.rb +94 -0
- data/lib/dbagile/core/schema.rb +254 -0
- data/lib/dbagile/core/transaction.rb +74 -0
- data/lib/dbagile/core.rb +7 -0
- data/lib/dbagile/environment/buffering.rb +45 -0
- data/lib/dbagile/environment/delegator.rb +59 -0
- data/lib/dbagile/environment/interactions.rb +208 -0
- data/lib/dbagile/environment/on_error.rb +47 -0
- data/lib/dbagile/environment/repository.rb +161 -0
- data/lib/dbagile/environment/robustness.rb +7 -0
- data/lib/dbagile/environment/testing.rb +23 -0
- data/lib/dbagile/environment.rb +122 -0
- data/lib/dbagile/errors.rb +30 -0
- data/lib/dbagile/io/csv.rb +99 -0
- data/lib/dbagile/io/json.rb +41 -0
- data/lib/dbagile/io/pretty_table.rb +128 -0
- data/lib/dbagile/io/ruby.rb +62 -0
- data/lib/dbagile/io/text.rb +18 -0
- data/lib/dbagile/io/type_safe.rb +65 -0
- data/lib/dbagile/io/xml.rb +35 -0
- data/lib/dbagile/io/yaml.rb +30 -0
- data/lib/dbagile/io.rb +94 -0
- data/lib/dbagile/loader.rb +16 -0
- data/lib/dbagile/plugin.rb +29 -0
- data/lib/dbagile/restful/client/delete.rb +22 -0
- data/lib/dbagile/restful/client/get.rb +24 -0
- data/lib/dbagile/restful/client/post.rb +22 -0
- data/lib/dbagile/restful/client/utils.rb +16 -0
- data/lib/dbagile/restful/client.rb +41 -0
- data/lib/dbagile/restful/middleware/delete.rb +22 -0
- data/lib/dbagile/restful/middleware/get.rb +27 -0
- data/lib/dbagile/restful/middleware/one_database.rb +82 -0
- data/lib/dbagile/restful/middleware/post.rb +23 -0
- data/lib/dbagile/restful/middleware/utils.rb +65 -0
- data/lib/dbagile/restful/middleware.rb +54 -0
- data/lib/dbagile/restful/server.rb +65 -0
- data/lib/dbagile/restful.rb +9 -0
- data/lib/dbagile/robustness/dependencies.rb +36 -0
- data/lib/dbagile/robustness/file_system.rb +53 -0
- data/lib/dbagile/robustness.rb +14 -0
- data/lib/dbagile/tools/file_system.rb +24 -0
- data/lib/dbagile/tools/math.rb +11 -0
- data/lib/dbagile/tools/ordered_hash.rb +39 -0
- data/lib/dbagile/tools/ruby.rb +78 -0
- data/lib/dbagile/tools/string.rb +6 -0
- data/lib/dbagile/tools/tuple.rb +49 -0
- data/lib/dbagile/tools.rb +6 -0
- data/lib/dbagile.rb +66 -0
- data/test/assumptions/equality.spec +11 -0
- data/test/assumptions/fixtures.rb +39 -0
- data/test/assumptions/inheritance.spec +17 -0
- data/test/assumptions/sequel/autonumber.spec +19 -0
- data/test/assumptions/sequel/connect.spec +29 -0
- data/test/assumptions/sequel/test.db +0 -0
- data/test/assumptions/stdlib/pathname.spec +13 -0
- data/test/assumptions/yaml/fixtures.rb +25 -0
- data/test/assumptions/yaml/to_yaml.spec +10 -0
- data/test/assumptions.spec +2 -0
- data/test/commands/bulk/export.spec +100 -0
- data/test/commands/bulk/import.spec +49 -0
- data/test/commands/db/add.spec +31 -0
- data/test/commands/db/list.spec +29 -0
- data/test/commands/db/ping.spec +21 -0
- data/test/commands/db/rm.spec +18 -0
- data/test/commands/db/use.spec +18 -0
- data/test/commands/dba.spec +54 -0
- data/test/commands/repo/create.spec +30 -0
- data/test/commands/schema/check.spec +25 -0
- data/test/commands/schema/diff.spec +30 -0
- data/test/commands/schema/dump.spec +23 -0
- data/test/commands/schema/fixtures/add_constraint.yaml +30 -0
- data/test/commands/schema/fixtures/announced.yaml +28 -0
- data/test/commands/schema/fixtures/effective.yaml +20 -0
- data/test/commands/schema/fixtures/invalid.yaml +6 -0
- data/test/commands/schema/sql_script.spec +56 -0
- data/test/commands/sql/drop.spec +25 -0
- data/test/commands/sql/heading.spec +7 -0
- data/test/commands/sql/scripts/delete.sql +1 -0
- data/test/commands/sql/scripts/insert.sql +2 -0
- data/test/commands/sql/send.spec +29 -0
- data/test/commands/sql/show.spec +17 -0
- data/test/commands.spec +138 -0
- data/test/contract/connection/transaction.ex +11 -0
- data/test/contract/connection.spec +9 -0
- data/test/contract/data/dataset/columns.ex +5 -0
- data/test/contract/data/dataset/count.ex +5 -0
- data/test/contract/data/dataset.spec +9 -0
- data/test/contract/data/table_driven/dataset.ex +31 -0
- data/test/contract/data/table_driven/exists_q.ex +27 -0
- data/test/contract/data/table_driven.spec +9 -0
- data/test/contract/data/transaction_driven/delete.ex +29 -0
- data/test/contract/data/transaction_driven/direct_sql.ex +19 -0
- data/test/contract/data/transaction_driven/insert.ex +8 -0
- data/test/contract/data/transaction_driven/update.ex +19 -0
- data/test/contract/data/transaction_driven.spec +18 -0
- data/test/contract/robust/data/table_driven.spec +15 -0
- data/test/contract/robust/data/transaction_driven.spec +21 -0
- data/test/contract/robust/schema/table_driven.spec +21 -0
- data/test/contract/robust/schema/transaction_driven.spec +19 -0
- data/test/contract/schema/table_driven/column_names.ex +5 -0
- data/test/contract/schema/table_driven/has_column_q.ex +13 -0
- data/test/contract/schema/table_driven/has_table_q.ex +11 -0
- data/test/contract/schema/table_driven/heading.ex +5 -0
- data/test/contract/schema/table_driven.spec +9 -0
- data/test/contract/schema/transaction_driven/create_table.ex +10 -0
- data/test/contract/schema/transaction_driven/drop_table.ex +10 -0
- data/test/contract/schema/transaction_driven.spec +18 -0
- data/test/contract.spec +66 -0
- data/test/fixtures/basics/data/basic_values.rb +13 -0
- data/test/fixtures/basics/data/empty_table.rb +3 -0
- data/test/fixtures/basics/data/non_empty_table.rb +4 -0
- data/test/fixtures/basics/data/parts.rb +8 -0
- data/test/fixtures/basics/data/suppliers.rb +7 -0
- data/test/fixtures/basics/data/supplies.rb +14 -0
- data/test/fixtures/basics/dbagile.idx +20 -0
- data/test/fixtures/basics/fixtures.yaml +28 -0
- data/test/fixtures/basics/robust.db +0 -0
- data/test/fixtures/basics/suppliers.yaml +30 -0
- data/test/fixtures/basics/test.db +0 -0
- data/test/fixtures/empty/dbagile.idx +5 -0
- data/test/fixtures.rb +152 -0
- data/test/restful/delete/no_format.ex +32 -0
- data/test/restful/delete.spec +8 -0
- data/test/restful/get/csv_format.ex +12 -0
- data/test/restful/get/json_format.ex +19 -0
- data/test/restful/get/query_string.ex +11 -0
- data/test/restful/get/text_format.ex +12 -0
- data/test/restful/get/yaml_format.ex +14 -0
- data/test/restful/get.spec +5 -0
- data/test/restful/post/no_format.ex +22 -0
- data/test/restful/post.spec +8 -0
- data/test/restful.spec +32 -0
- data/test/run_all_suite.rb +51 -0
- data/test/spec_helper.rb +26 -0
- data/test/support/be_a_valid_json_string.rb +19 -0
- data/test/support/be_a_valid_yaml_string.rb +18 -0
- data/test/unit/adapter/factor.spec +13 -0
- data/test/unit/adapter/sequel/new.spec +19 -0
- data/test/unit/command/api.spec +12 -0
- data/test/unit/command/command_for.spec +36 -0
- data/test/unit/command/command_name_of.spec +21 -0
- data/test/unit/command/ruby_method_for.spec +21 -0
- data/test/unit/command/sanity.spec +34 -0
- data/test/unit/contract/utils/delegate/delegate.spec +23 -0
- data/test/unit/core/chain/chain.spec +57 -0
- data/test/unit/core/chain/connect.spec +22 -0
- data/test/unit/core/chain/delegate_chain.spec +16 -0
- data/test/unit/core/chain/initialize.spec +19 -0
- data/test/unit/core/chain/plug.spec +31 -0
- data/test/unit/core/io/dsl/scope.spec +9 -0
- data/test/unit/core/repository/create_bang.spec +31 -0
- data/test/unit/core/repository/current.spec +31 -0
- data/test/unit/core/repository/database.spec +47 -0
- data/test/unit/core/repository/fixtures/corrupted/dbagile.idx +1 -0
- data/test/unit/core/repository/fixtures/test_and_prod/dbagile.idx +21 -0
- data/test/unit/core/repository/fixtures.rb +25 -0
- data/test/unit/core/repository/has_database_q.spec +16 -0
- data/test/unit/core/repository/load.spec +51 -0
- data/test/unit/core/repository/to_yaml.spec +17 -0
- data/test/unit/core/schema/check.spec +32 -0
- data/test/unit/core/schema/empty_q.spec +18 -0
- data/test/unit/core/schema/filter.spec +42 -0
- data/test/unit/core/schema/fixtures/dbagile.yaml +7 -0
- data/test/unit/core/schema/fixtures/empty.yaml +11 -0
- data/test/unit/core/schema/fixtures/invalid.yaml +54 -0
- data/test/unit/core/schema/fixtures/left.yaml +46 -0
- data/test/unit/core/schema/fixtures/left_minus_right.yaml +31 -0
- data/test/unit/core/schema/fixtures/right.yaml +46 -0
- data/test/unit/core/schema/fixtures/right_minus_left.yaml +31 -0
- data/test/unit/core/schema/fixtures/suppliers_and_parts.yaml +30 -0
- data/test/unit/core/schema/fixtures.rb +32 -0
- data/test/unit/core/schema/merge.spec +72 -0
- data/test/unit/core/schema/minus.spec +26 -0
- data/test/unit/core/schema/sanity.spec +39 -0
- data/test/unit/core/schema/split.spec +58 -0
- data/test/unit/core/schema/stage_script.spec +26 -0
- data/test/unit/core/schema/to_yaml.spec +13 -0
- data/test/unit/core/schema/yaml_display.spec +14 -0
- data/test/unit/core/schema/yaml_load.spec +20 -0
- data/test/unit/core/transaction/transaction.spec +10 -0
- data/test/unit/fixtures.rb +67 -0
- data/test/unit/io/to_xxx.spec +52 -0
- data/test/unit/plugin/options.spec +21 -0
- data/test/unit/plugin/tuple_heading.spec +11 -0
- data/test/unit/plugin/with_options.spec +12 -0
- data/test/unit/tools/ruby/class_unqualified_name.spec +26 -0
- data/test/unit/tools/ruby/extract_file_rdoc.spec +10 -0
- data/test/unit/tools/ruby/fixtures/rdoc.txt +12 -0
- data/test/unit/tools/ruby/fixtures.rb +19 -0
- data/test/unit/tools/ruby/optional_args_block_call.spec +35 -0
- data/test/unit/tools/ruby/parent_module.spec +21 -0
- data/test/unit/tools/ruby/rdoc_file_paragraphs.spec +13 -0
- data/test/unit/tools/tuple/tuple_heading.spec +11 -0
- data/test/unit/tools/tuple/tuple_key.spec +27 -0
- data/test/unit/tools/tuple/tuple_project.spec +23 -0
- data/test/unit.spec +3 -0
- metadata +422 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
#
|
|
4
|
+
# Encapsulates a database handler.
|
|
5
|
+
#
|
|
6
|
+
class Database
|
|
7
|
+
|
|
8
|
+
# Database name
|
|
9
|
+
attr_reader :name
|
|
10
|
+
|
|
11
|
+
# Database uri
|
|
12
|
+
attr_accessor :uri
|
|
13
|
+
|
|
14
|
+
# Array of files for the announced schema
|
|
15
|
+
attr_accessor :announced_files
|
|
16
|
+
alias :announced_schema= :announced_files=
|
|
17
|
+
|
|
18
|
+
# Array of files for the effective schema
|
|
19
|
+
attr_accessor :effective_files
|
|
20
|
+
alias :effective_schema= :effective_files=
|
|
21
|
+
|
|
22
|
+
# Resolves relative files
|
|
23
|
+
attr_accessor :file_resolver
|
|
24
|
+
|
|
25
|
+
# Plugs as arrays of arrays
|
|
26
|
+
attr_reader :plugs
|
|
27
|
+
|
|
28
|
+
# Creates a database instance
|
|
29
|
+
def initialize(name, uri = nil, &block)
|
|
30
|
+
raise ArgumentError, "Database name is mandatory" unless name.kind_of?(Symbol)
|
|
31
|
+
raise ArgumentError, "Database DSL is deprecated" unless block.nil?
|
|
32
|
+
@name = name
|
|
33
|
+
@uri = uri
|
|
34
|
+
@announced_files = []
|
|
35
|
+
@effective_files = []
|
|
36
|
+
@file_resolver = lambda{|f| ::File.expand_path(f) }
|
|
37
|
+
@chain = ::DbAgile::Core::Chain.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
##############################################################################
|
|
43
|
+
### About connector
|
|
44
|
+
##############################################################################
|
|
45
|
+
|
|
46
|
+
# @see Chain#plug
|
|
47
|
+
def plug(*args)
|
|
48
|
+
(@plugs ||= []).push(*args)
|
|
49
|
+
@chain.plug(*args)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Installs plugins
|
|
53
|
+
def plugins=(plugins)
|
|
54
|
+
plugins = plugins.collect{|p| Kernel.eval(p)}
|
|
55
|
+
plug(*plugins)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
##############################################################################
|
|
60
|
+
### About connection
|
|
61
|
+
##############################################################################
|
|
62
|
+
|
|
63
|
+
# Checks if the connection pings correctly.
|
|
64
|
+
def ping?
|
|
65
|
+
connect.ping?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Connects and returns a Connection object
|
|
69
|
+
def connect(options = {})
|
|
70
|
+
raise ArgumentError, "Options should be a Hash" unless options.kind_of?(Hash)
|
|
71
|
+
raise DbAgile::Error, "Database has no uri" if uri.nil?
|
|
72
|
+
if uri =~ /:\/\//
|
|
73
|
+
adapter = DbAgile::Adapter::factor(uri, options)
|
|
74
|
+
elsif file_resolver
|
|
75
|
+
file = file_resolver.call(uri)
|
|
76
|
+
adapter = DbAgile::Adapter::factor("sqlite://#{file}", options)
|
|
77
|
+
else
|
|
78
|
+
raise DbAgile::Error, "A file resolver is required for using #{uri} as database uri"
|
|
79
|
+
end
|
|
80
|
+
connector = @chain.connect(adapter)
|
|
81
|
+
Connection.new(connector)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
#
|
|
85
|
+
# Yields the block with a connection; disconnect after that.
|
|
86
|
+
#
|
|
87
|
+
# @raise ArgumentError if no block is provided
|
|
88
|
+
# @return block execution result
|
|
89
|
+
#
|
|
90
|
+
def with_connection(conn_options = {})
|
|
91
|
+
raise ArgumentError, "Missing block" unless block_given?
|
|
92
|
+
begin
|
|
93
|
+
connection = connect(conn_options)
|
|
94
|
+
result = yield(connection)
|
|
95
|
+
result
|
|
96
|
+
ensure
|
|
97
|
+
connection.disconnect if connection
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
##############################################################################
|
|
102
|
+
### About schema
|
|
103
|
+
##############################################################################
|
|
104
|
+
|
|
105
|
+
# Does this database has announced schema files?
|
|
106
|
+
def has_announced_schema?
|
|
107
|
+
!(@announced_files.nil? or @announced_files.empty?)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Does this database has effective schema files?
|
|
111
|
+
def has_effective_schema?
|
|
112
|
+
!(@effective_files.nil? or @effective_files.empty?)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Loads a schema from schema files
|
|
116
|
+
def load_schema_from_files(files)
|
|
117
|
+
builder = DbAgile::Core::Schema::builder
|
|
118
|
+
builder.schema(files){
|
|
119
|
+
files.collect{|f| file_resolver.call(f)}.each{|f|
|
|
120
|
+
DbAgile::Core::Schema::yaml_file_load(f, builder)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
builder._dump
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Returns the schema of highest level (announced -> effective -> physical).
|
|
127
|
+
def schema
|
|
128
|
+
announced_schema(true)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Returns the announced schema. If no announce schema files are installed
|
|
132
|
+
# and unstage is true, returns the effective schema. Returns nil otherwise.
|
|
133
|
+
def announced_schema(unstage = false)
|
|
134
|
+
if has_announced_schema?
|
|
135
|
+
load_schema_from_files(announced_files)
|
|
136
|
+
elsif unstage
|
|
137
|
+
effective_schema(unstage)
|
|
138
|
+
else
|
|
139
|
+
nil
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Overrides announced schema with a given schema
|
|
144
|
+
def set_announced_schema(schema)
|
|
145
|
+
# Set announced files
|
|
146
|
+
self.announced_files ||= []
|
|
147
|
+
case announced_files.size
|
|
148
|
+
when 0
|
|
149
|
+
FileUtils.mkdir_p(file_resolver.call(name))
|
|
150
|
+
self.announced_files = [ "#{name}/announced.yaml" ]
|
|
151
|
+
when 1
|
|
152
|
+
else
|
|
153
|
+
raise "Unable to set announced schema with multiple effective files"
|
|
154
|
+
end
|
|
155
|
+
::File.open(file_resolver.call(announced_files[0]), 'w') do |io|
|
|
156
|
+
io << schema.to_yaml
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Returns the effective schema. If no effective files are installed and
|
|
161
|
+
# unstage is true, returns the physical schema. Returns nil otherwise.
|
|
162
|
+
def effective_schema(unstage = false)
|
|
163
|
+
if has_effective_schema?
|
|
164
|
+
load_schema_from_files(effective_files)
|
|
165
|
+
elsif unstage
|
|
166
|
+
physical_schema
|
|
167
|
+
else
|
|
168
|
+
nil
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Overrides effective schema with a given schema
|
|
173
|
+
def set_effective_schema(schema)
|
|
174
|
+
# Set effective files
|
|
175
|
+
self.effective_files ||= []
|
|
176
|
+
case effective_files.size
|
|
177
|
+
when 0
|
|
178
|
+
FileUtils.mkdir_p(file_resolver.call(name.to_s))
|
|
179
|
+
self.effective_files = [ "#{name}/effective.yaml" ]
|
|
180
|
+
when 1
|
|
181
|
+
else
|
|
182
|
+
raise "Unable to set effective schema with multiple effective files"
|
|
183
|
+
end
|
|
184
|
+
::File.open(file_resolver.call(effective_files[0]), 'w') do |io|
|
|
185
|
+
io << schema.to_yaml
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Returns the database physical schema
|
|
190
|
+
def physical_schema
|
|
191
|
+
with_connection{|c| c.physical_schema}
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
private :load_schema_from_files
|
|
195
|
+
|
|
196
|
+
##############################################################################
|
|
197
|
+
### About io
|
|
198
|
+
##############################################################################
|
|
199
|
+
|
|
200
|
+
# Converts this database to a yaml string
|
|
201
|
+
def to_yaml(opts = {})
|
|
202
|
+
YAML::quick_emit(self, opts){|out|
|
|
203
|
+
out.map("tag:yaml.org,2002:map") do |map|
|
|
204
|
+
map.add('uri', self.uri)
|
|
205
|
+
if has_announced_schema?
|
|
206
|
+
map.add('announced_schema', self.announced_files || [])
|
|
207
|
+
end
|
|
208
|
+
if has_effective_schema?
|
|
209
|
+
map.add('effective_schema', self.effective_files || [])
|
|
210
|
+
end
|
|
211
|
+
if plugs and not(plugs.empty?)
|
|
212
|
+
ps = plugs.collect{|p| SByC::TypeSystem::Ruby::to_literal(p)}
|
|
213
|
+
map.add('plugins', ps)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end # class Database
|
|
220
|
+
end # module Core
|
|
221
|
+
end # module DbAgile
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module IO
|
|
4
|
+
class DSL
|
|
5
|
+
include DbAgile::Core::IO::Robustness
|
|
6
|
+
|
|
7
|
+
# The Repository instance passed at construction
|
|
8
|
+
attr_reader :repository
|
|
9
|
+
|
|
10
|
+
# The current Database instance
|
|
11
|
+
attr_reader :current_database
|
|
12
|
+
|
|
13
|
+
# Creates a DSL instance
|
|
14
|
+
def initialize(repository = nil, database = nil, &block)
|
|
15
|
+
@repository = repository
|
|
16
|
+
@current_database = database
|
|
17
|
+
self.instance_eval(&block) unless block.nil?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Adds a database under a given name
|
|
21
|
+
def database(name, &block)
|
|
22
|
+
valid_database_name!(name)
|
|
23
|
+
created = with_database(Core::Database.new(name)){|cfg|
|
|
24
|
+
self.instance_eval(&block)
|
|
25
|
+
cfg
|
|
26
|
+
}
|
|
27
|
+
unless repository.nil?
|
|
28
|
+
repository << created
|
|
29
|
+
end
|
|
30
|
+
created
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Sets the uri on the current database
|
|
34
|
+
def uri(str)
|
|
35
|
+
dsl_has_database!
|
|
36
|
+
valid_database_uri!(str)
|
|
37
|
+
current_database.uri = str
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Sets the announced schema files
|
|
41
|
+
def announced_schema(*files)
|
|
42
|
+
dsl_has_database!
|
|
43
|
+
current_database.announced_files = valid_schema_files!(files)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Sets the effective schema files
|
|
47
|
+
def effective_schema(*files)
|
|
48
|
+
dsl_has_database!
|
|
49
|
+
current_database.effective_files = valid_schema_files!(files)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @see DbAgile::Core::Database#plug
|
|
53
|
+
def plug(*args)
|
|
54
|
+
dsl_has_database!
|
|
55
|
+
current_database.plug(*args)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Sets the current database
|
|
59
|
+
def current_db(name)
|
|
60
|
+
dsl_has_repository!
|
|
61
|
+
repository.current_db_name = name
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
###
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
# Yields the block with a database
|
|
69
|
+
def with_database(db)
|
|
70
|
+
if db.kind_of?(DbAgile::Core::Database)
|
|
71
|
+
@current_database = db
|
|
72
|
+
result = yield(db)
|
|
73
|
+
@current_database = nil
|
|
74
|
+
result
|
|
75
|
+
elsif db.kind_of?(Symbol) or db.nil?
|
|
76
|
+
dsl_has_repository!
|
|
77
|
+
has_database!(repository, cfg)
|
|
78
|
+
with_database(repository.database(cfg), &block)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Asserts that there is a current database
|
|
83
|
+
def dsl_has_database!
|
|
84
|
+
raise DbAgile::Error, "Invalid Core::IO::DSL usage, no current database" if current_database.nil?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Asserts that there is a current repository
|
|
88
|
+
def dsl_has_repository!
|
|
89
|
+
raise DbAgile::Error, "Invalid Core::IO::DSL usage, no current repository" if repository.nil?
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end # class DSL
|
|
93
|
+
end # module IO
|
|
94
|
+
end # module Core
|
|
95
|
+
end # module DbAgile
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module IO
|
|
4
|
+
module Robustness
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Asserts that a database name is valid or raises a InvalidDatabaseName
|
|
8
|
+
# error. A valid database name is a Symbol that matches /[a-z][a-z0-9_]*/.
|
|
9
|
+
#
|
|
10
|
+
# @returns [Symbol] name
|
|
11
|
+
# @raise DbAgile::InvalidDatabaseName if assertion fails
|
|
12
|
+
#
|
|
13
|
+
def valid_database_name!(name)
|
|
14
|
+
raise DbAgile::InvalidDatabaseName, "Invalid database name #{name}"\
|
|
15
|
+
unless name.kind_of?(Symbol) and /[a-z][a-z0-9_]*/ =~ name.to_s
|
|
16
|
+
name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
#
|
|
20
|
+
# Asserts that a database uri is valid or raises a InvalidDatabaseUri error.
|
|
21
|
+
#
|
|
22
|
+
# A valid database uri is any valid absolute URI (for now, will be restricted
|
|
23
|
+
# to known adapters in the future).
|
|
24
|
+
#
|
|
25
|
+
# @return [String] uri
|
|
26
|
+
# @raise DbAgile::InvalidDatabaseUri if assertion fails
|
|
27
|
+
#
|
|
28
|
+
def valid_database_uri!(uri)
|
|
29
|
+
require 'uri'
|
|
30
|
+
got = URI::parse(uri)
|
|
31
|
+
if got.scheme or (uri =~ /\.db$/)
|
|
32
|
+
uri
|
|
33
|
+
else
|
|
34
|
+
raise DbAgile::InvalidDatabaseUri, "Invalid database uri: #{uri}"
|
|
35
|
+
end
|
|
36
|
+
rescue URI::InvalidURIError
|
|
37
|
+
raise DbAgile::InvalidDatabaseUri, "Invalid database uri: #{uri}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#
|
|
41
|
+
# Asserts that a database exists inside a Repository instance.
|
|
42
|
+
# When db_name is nil, asserts that a default database is set.
|
|
43
|
+
#
|
|
44
|
+
# @param [DbAgile::Core::Repository] a repository
|
|
45
|
+
# @return [DbAgile::Core::Database] the database instance when found.
|
|
46
|
+
# @raise ArgumentError if repository is not a Repository instance
|
|
47
|
+
# @raise DbAgile::NoSuchDatabaseError if the database cannot be found.
|
|
48
|
+
# @raise DbAgile::NoDefaultDatabaseError if db_name is nil and no
|
|
49
|
+
# current database is set on the repository.
|
|
50
|
+
#
|
|
51
|
+
def has_database!(repository, db_name = nil)
|
|
52
|
+
raise ArgumentError, "Repository expected, got #{repository}"\
|
|
53
|
+
unless repository.kind_of?(DbAgile::Core::Repository)
|
|
54
|
+
db = if db_name.nil?
|
|
55
|
+
repository.current_database
|
|
56
|
+
else
|
|
57
|
+
repository.database(db_name)
|
|
58
|
+
end
|
|
59
|
+
if db.nil?
|
|
60
|
+
raise DbAgile::NoSuchDatabaseError, "Unknown database #{db_name}" if db_name
|
|
61
|
+
raise DbAgile::NoDefaultDatabaseError, "No default database set (try 'dba use ...' first)"
|
|
62
|
+
else
|
|
63
|
+
db
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
#
|
|
68
|
+
# Coerces and asserts that schema files arguments are correct.
|
|
69
|
+
# Returns normalized version.
|
|
70
|
+
#
|
|
71
|
+
def valid_schema_files!(*files)
|
|
72
|
+
files = files.flatten
|
|
73
|
+
unless files.all?{|f| f.kind_of?(String)}
|
|
74
|
+
raise DbAgile::CorruptedRepositoryError, "Invalid schema files #{files.inspect}"
|
|
75
|
+
end
|
|
76
|
+
files
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end # module Robustness
|
|
80
|
+
end # module IO
|
|
81
|
+
end # module Core
|
|
82
|
+
end # module DbAgile
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
class Repository
|
|
4
|
+
class Builder
|
|
5
|
+
include DbAgile::Environment::Delegator
|
|
6
|
+
|
|
7
|
+
# Environment to use
|
|
8
|
+
attr_reader :environment
|
|
9
|
+
|
|
10
|
+
# Creates a builder instance
|
|
11
|
+
def initialize(env)
|
|
12
|
+
@environment = env
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Ensures that the repository exists. If not, ask the user about creating
|
|
17
|
+
# one in interactive mode; raises an error otherwise. Continues execution
|
|
18
|
+
# with the provided block if required.
|
|
19
|
+
#
|
|
20
|
+
def ensure_repository(&block)
|
|
21
|
+
env = self.environment
|
|
22
|
+
if env.repository_exists?
|
|
23
|
+
block.call if block
|
|
24
|
+
elsif env.interactive?
|
|
25
|
+
where = env.friendly_repository_path
|
|
26
|
+
msg = <<-EOF.gsub(/^\s*\| ?/, '')
|
|
27
|
+
| DbAgile's repository #{where} does not exist. Maybe it's the first time you
|
|
28
|
+
| lauch dba. Do you want to create a fresh repository now?
|
|
29
|
+
EOF
|
|
30
|
+
confirm(msg, "Have a look at 'dba help repo:create'"){
|
|
31
|
+
# create it!
|
|
32
|
+
say("Creating repository #{where}...")
|
|
33
|
+
DbAgile::Core::Repository::create!(env.repository_path)
|
|
34
|
+
say("Repository has been successfully created.")
|
|
35
|
+
|
|
36
|
+
# continue?
|
|
37
|
+
if block
|
|
38
|
+
msg = "Do you want to continue with previous command execution?"
|
|
39
|
+
confirm(msg, &block)
|
|
40
|
+
end
|
|
41
|
+
}
|
|
42
|
+
else
|
|
43
|
+
# to force an error
|
|
44
|
+
environment.repository
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Yields the block if the user confirms something and returns block
|
|
49
|
+
# execution. Returns nil otherwise
|
|
50
|
+
#
|
|
51
|
+
def confirm(msg, on_no_msg = nil)
|
|
52
|
+
say("\n")
|
|
53
|
+
say(msg, :magenta)
|
|
54
|
+
answer = environment.ask(""){|q| q.validate = /^y(es)?|n(o)?|q(uit)?/i}
|
|
55
|
+
case answer.strip
|
|
56
|
+
when /^n/i, /^q/i
|
|
57
|
+
say("\n")
|
|
58
|
+
say(on_no_msg, :magenta) unless on_no_msg.nil?
|
|
59
|
+
when /^y/i
|
|
60
|
+
yield
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end # class Builder
|
|
65
|
+
end # class Repository
|
|
66
|
+
end # module Core
|
|
67
|
+
end # module DbAgile
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
class Repository
|
|
4
|
+
|
|
5
|
+
module YAMLInstanceMethods
|
|
6
|
+
|
|
7
|
+
# Dumps the repository to YAML
|
|
8
|
+
def to_yaml(opts = {})
|
|
9
|
+
YAML::quick_emit(self, opts){|out|
|
|
10
|
+
dbmap = DbAgile::Tools::OrderedHash.new
|
|
11
|
+
databases.each{|db| dbmap[db.name.to_s] = db}
|
|
12
|
+
out.map("tag:yaml.org,2002:map") do |map|
|
|
13
|
+
map.add('version', self.version)
|
|
14
|
+
map.add('databases', dbmap)
|
|
15
|
+
map.add('current', self.current_db_name.to_s)
|
|
16
|
+
end
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end # module YAMLInstanceMethods
|
|
21
|
+
|
|
22
|
+
module YAMLClassMethods
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# Loads a repository from a YAML file and returns a Core::Repository instance.
|
|
26
|
+
#
|
|
27
|
+
# This method is not robust at all and re-raises any error that occurs. It
|
|
28
|
+
# should be protected upstream.
|
|
29
|
+
#
|
|
30
|
+
# @param [String] file path to a repository index (exist, readable)
|
|
31
|
+
# @param [String] root_path path of the repository itself (exist, readable)
|
|
32
|
+
# @raise DbAgile::CorruptedRepositoryError if anything goes wrong.
|
|
33
|
+
#
|
|
34
|
+
def from_yaml_file(file, root_path)
|
|
35
|
+
from_yaml(File.read(file), root_path)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Loads a repository from a YAML file and returns a Core::Repository instance.
|
|
40
|
+
#
|
|
41
|
+
# This method is not robust at all and re-raises any error that occurs. It
|
|
42
|
+
# should be protected upstream.
|
|
43
|
+
#
|
|
44
|
+
# @param [String] str a YAML source
|
|
45
|
+
# @param [String] root_path root path to set on the repository
|
|
46
|
+
#
|
|
47
|
+
def from_yaml(str, root_path)
|
|
48
|
+
# Load the hash
|
|
49
|
+
hash = YAML::load(str)
|
|
50
|
+
|
|
51
|
+
# Load the repository version
|
|
52
|
+
version = hash['version'].to_s.strip
|
|
53
|
+
if version.nil? or version.empty?
|
|
54
|
+
raise "missing version number"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# create the repository instance
|
|
58
|
+
repo = Repository.new(root_path, version)
|
|
59
|
+
|
|
60
|
+
# load databases
|
|
61
|
+
hash['databases'].each_pair{|dbname, dbconfig|
|
|
62
|
+
db = Core::Database.new(dbname.to_s.to_sym)
|
|
63
|
+
dbconfig.each_pair{|key, value|
|
|
64
|
+
db.send(:"#{key}=", value)
|
|
65
|
+
}
|
|
66
|
+
repo << db
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Set current database
|
|
70
|
+
current = hash['current'].to_s.strip
|
|
71
|
+
unless current.empty?
|
|
72
|
+
repo.current_db_name = current.to_sym
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
repo
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end # module YAMLClassMethods
|
|
79
|
+
|
|
80
|
+
end # class Repository
|
|
81
|
+
end # module Core
|
|
82
|
+
end # module DbAgile
|