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,35 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class AbstractScript
|
|
6
|
+
include Enumerable
|
|
7
|
+
|
|
8
|
+
# Operations in this abstract script
|
|
9
|
+
attr_reader :operations
|
|
10
|
+
|
|
11
|
+
# Creates an abstract script instance
|
|
12
|
+
def initialize
|
|
13
|
+
@operations = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Yields the block with each operation in turn
|
|
17
|
+
def each(&block)
|
|
18
|
+
operations.each(&block)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Pushes operations in this abstract script
|
|
22
|
+
def <<(*ops)
|
|
23
|
+
self.operations.push(*ops)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # class AbstractScript
|
|
27
|
+
end # module Migrate
|
|
28
|
+
end # module Schema
|
|
29
|
+
end # module Core
|
|
30
|
+
end # module DbAgile
|
|
31
|
+
require 'dbagile/core/schema/migrate/operation'
|
|
32
|
+
require 'dbagile/core/schema/migrate/create_table'
|
|
33
|
+
require 'dbagile/core/schema/migrate/drop_table'
|
|
34
|
+
require 'dbagile/core/schema/migrate/expand_table'
|
|
35
|
+
require 'dbagile/core/schema/migrate/collapse_table'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class CollapseTable < Migrate::Operation
|
|
6
|
+
|
|
7
|
+
def to_sql92
|
|
8
|
+
"ALTER TABLE DROP #{ops_to_sql92(operations)}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end # class CollapseTable
|
|
12
|
+
end # module Migrate
|
|
13
|
+
end # module Schema
|
|
14
|
+
end # module Core
|
|
15
|
+
end # module DbAgile
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class CreateTable < Migrate::Operation
|
|
6
|
+
|
|
7
|
+
def to_sql92
|
|
8
|
+
"CREATE TABLE (#{ops_to_sql92(operations)})"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end # class CreateTable
|
|
12
|
+
end # module Migrate
|
|
13
|
+
end # module Schema
|
|
14
|
+
end # module Core
|
|
15
|
+
end # module DbAgile
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class DropTable < Migrate::Operation
|
|
6
|
+
|
|
7
|
+
def to_sql92
|
|
8
|
+
"DROP TABLE #{table_name}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end # class DropTable
|
|
12
|
+
end # module Migrate
|
|
13
|
+
end # module Schema
|
|
14
|
+
end # module Core
|
|
15
|
+
end # module DbAgile
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class ExpandTable < Migrate::Operation
|
|
6
|
+
|
|
7
|
+
def to_sql92
|
|
8
|
+
"ALTER TABLE ADD #{ops_to_sql92(operations)}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end # class ExpandTable
|
|
12
|
+
end # module Migrate
|
|
13
|
+
end # module Schema
|
|
14
|
+
end # module Core
|
|
15
|
+
end # module DbAgile
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class Operation
|
|
6
|
+
|
|
7
|
+
# The sub operations
|
|
8
|
+
attr_reader :operations
|
|
9
|
+
|
|
10
|
+
# Targetted relation variable
|
|
11
|
+
attr_reader :relvar
|
|
12
|
+
|
|
13
|
+
# Returns table name
|
|
14
|
+
def table_name
|
|
15
|
+
relvar.name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(relvar)
|
|
19
|
+
unless relvar.kind_of?(DbAgile::Core::Schema::Logical::Relvar)
|
|
20
|
+
raise ArgumentError, "Relvar expected for relvar, got #{relvar.class}"
|
|
21
|
+
end
|
|
22
|
+
@relvar = relvar
|
|
23
|
+
@operations = []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns kind of this operation
|
|
27
|
+
def kind
|
|
28
|
+
unqualified = DbAgile::RubyTools::class_unqualified_name(self.class).to_s
|
|
29
|
+
unqualified.gsub(/[A-Z]/){|x| "_#{x.downcase}"}[1..-1].to_sym
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##########################################################################
|
|
33
|
+
### Execution feedback
|
|
34
|
+
##########################################################################
|
|
35
|
+
|
|
36
|
+
# Mark an object as upgraded
|
|
37
|
+
def staged!(obj = relvar)
|
|
38
|
+
obj.status = case obj.status
|
|
39
|
+
when Schema::TO_CREATE, Schema::CREATED
|
|
40
|
+
Schema::CREATED
|
|
41
|
+
when Schema::TO_ALTER, Schema::ALTERED
|
|
42
|
+
Schema::ALTERED
|
|
43
|
+
when Schema::TO_DROP, Schema::DROPPED
|
|
44
|
+
Schema::DROPPED
|
|
45
|
+
when Schema::NO_CHANGE
|
|
46
|
+
Schema::NO_CHANGE
|
|
47
|
+
else
|
|
48
|
+
status_str = obj.status.to_s.upcase
|
|
49
|
+
raise DbAgile::AssumptionFailedError, "Unexpected staged! source status #{status_str} on #{obj}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Mark an object as not being staged
|
|
54
|
+
def not_staged!(obj = relvar)
|
|
55
|
+
obj.status = case obj.status
|
|
56
|
+
when Schema::TO_CREATE
|
|
57
|
+
Schema::DEFERED
|
|
58
|
+
when Schema::TO_ALTER
|
|
59
|
+
Schema::DEFERED
|
|
60
|
+
when Schema::TO_DROP
|
|
61
|
+
Schema::DEFERED
|
|
62
|
+
when Schema::DEFERED
|
|
63
|
+
Schema::DEFERED
|
|
64
|
+
when Schema::NO_CHANGE
|
|
65
|
+
Schema::NO_CHANGE
|
|
66
|
+
else
|
|
67
|
+
status_str = obj.status.to_s.upcase
|
|
68
|
+
raise DbAgile::AssumptionFailedError, "Unexpected staged! source status #{status_str} on #{obj}"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
##########################################################################
|
|
73
|
+
### About sub operations
|
|
74
|
+
##########################################################################
|
|
75
|
+
|
|
76
|
+
# Asserts that this operation supports sub operations
|
|
77
|
+
def supports_sub_operation?(name = nil)
|
|
78
|
+
!self.kind_of?(Migrate::DropTable)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Asserts that this operation supports sub operations
|
|
82
|
+
def supports_sub_operation!(name)
|
|
83
|
+
unless supports_sub_operation?(name)
|
|
84
|
+
raise DbAgile::AssumptionFailedError, "#{self.class} does not support sub operation #{name}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Yields the block with each (subop_kind, operand) pair
|
|
89
|
+
def each_sub_operation(&block)
|
|
90
|
+
supports_sub_operation!(nil)
|
|
91
|
+
operations.each{|op| block.call(op[0], op[1])}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Create/alter an attribute
|
|
95
|
+
def attribute(attribute)
|
|
96
|
+
supports_sub_operation!(:attribute)
|
|
97
|
+
operations << [:attribute, attribute]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Create/alter a candidate key
|
|
101
|
+
def candidate_key(ckey)
|
|
102
|
+
supports_sub_operation!(:candidate_key)
|
|
103
|
+
operations << [:candidate_key, ckey]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Create/alter a foreign key
|
|
107
|
+
def foreign_key(fkey)
|
|
108
|
+
supports_sub_operation!(:foreign_key)
|
|
109
|
+
operations << [:foreign_key, fkey]
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Create/alter an index
|
|
113
|
+
def index(index)
|
|
114
|
+
supports_sub_operation!(:index)
|
|
115
|
+
operations << [:index, index]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Converts operations to simili SQL
|
|
119
|
+
def ops_to_sql92(ops)
|
|
120
|
+
ops.collect{|op|
|
|
121
|
+
kind, operand = op
|
|
122
|
+
case kind
|
|
123
|
+
when :attribute
|
|
124
|
+
"COLUMN #{operand.name} #{operand.domain}"
|
|
125
|
+
when :candidate_key
|
|
126
|
+
"CANDIDATE KEY #{operand.name})"
|
|
127
|
+
when :foreign_key
|
|
128
|
+
"FOREIGN KEY #{operand.name}"
|
|
129
|
+
when :index
|
|
130
|
+
"INDEX #{operand.name}"
|
|
131
|
+
else
|
|
132
|
+
raise DbAgile::AssumptionFailedError, "Unexpected operation kin #{kind}"
|
|
133
|
+
end
|
|
134
|
+
}.join(';')
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end # class Operation
|
|
138
|
+
end # module Migrate
|
|
139
|
+
end # module Schema
|
|
140
|
+
end # module Core
|
|
141
|
+
end # module DbAgile
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
module Migrate
|
|
5
|
+
class Stager
|
|
6
|
+
|
|
7
|
+
# List of status
|
|
8
|
+
Status = ::DbAgile::Core::Schema
|
|
9
|
+
|
|
10
|
+
# Default stager options
|
|
11
|
+
DEFAULT_OPTIONS = {:expand => true, :collapse => true}
|
|
12
|
+
|
|
13
|
+
# The abstract script we build
|
|
14
|
+
attr_reader :script
|
|
15
|
+
|
|
16
|
+
# Helper for each relation variable
|
|
17
|
+
attr_reader :helpers
|
|
18
|
+
|
|
19
|
+
# Status of each object
|
|
20
|
+
attr_reader :status
|
|
21
|
+
|
|
22
|
+
############################################################################
|
|
23
|
+
### Schema info helpers need
|
|
24
|
+
############################################################################
|
|
25
|
+
|
|
26
|
+
# Checks if table already exists
|
|
27
|
+
def relvar_exists?(rv)
|
|
28
|
+
(rv.status == Status::NO_CHANGE) or
|
|
29
|
+
(rv.status == Status::TO_ALTER) or
|
|
30
|
+
(status[rv] == Status::CREATED)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Asserts that a table exists
|
|
34
|
+
def relvar_exists!(rv)
|
|
35
|
+
status[rv] = Status::CREATED
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
############################################################################
|
|
39
|
+
### Public interface
|
|
40
|
+
############################################################################
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# Runs the staging algorithm on an annotated schema (result of a merge)
|
|
44
|
+
# and options.
|
|
45
|
+
#
|
|
46
|
+
def run(schema, options)
|
|
47
|
+
@helpers = {}
|
|
48
|
+
@status = {}
|
|
49
|
+
@script = Migrate::AbstractScript.new
|
|
50
|
+
|
|
51
|
+
# Take all objects and mark them as :to_ensure
|
|
52
|
+
all_objects = schema.collect{|o, parent| o}
|
|
53
|
+
all_objects.each{|o| @status[o] = o.status}
|
|
54
|
+
|
|
55
|
+
# Collapse first
|
|
56
|
+
if options[:collapse]
|
|
57
|
+
collapse_objects(all_objects.select{|obj| @status[obj] == Status::TO_DROP})
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Expand then
|
|
61
|
+
if options[:expand]
|
|
62
|
+
expand_objects(all_objects.select{|obj| @status[obj] == Status::TO_CREATE})
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# clean
|
|
66
|
+
raise AssumptionFailedError, "Helpers should be empty" unless @helpers.empty?
|
|
67
|
+
to_return = @script
|
|
68
|
+
@script = nil
|
|
69
|
+
@helpers = nil
|
|
70
|
+
@status = nil
|
|
71
|
+
to_return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
############################################################################
|
|
75
|
+
### Collapse algorithms (for drop)
|
|
76
|
+
############################################################################
|
|
77
|
+
|
|
78
|
+
# Yields the block with an helper to collapse a relation
|
|
79
|
+
# variable, creating it if required.
|
|
80
|
+
def with_collapse_helper(rv)
|
|
81
|
+
if h = helpers[rv]
|
|
82
|
+
yield(h)
|
|
83
|
+
else
|
|
84
|
+
h = helpers[rv] = Migrate::CollapseTable.new(rv)
|
|
85
|
+
yield(h)
|
|
86
|
+
script << h
|
|
87
|
+
helpers.delete(rv)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Ensures inexistence of a list of schema objects
|
|
92
|
+
def collapse_objects(schema_objects)
|
|
93
|
+
schema_objects.each do |object|
|
|
94
|
+
case s = status[object]
|
|
95
|
+
when Status::TO_DROP, Status::TO_ALTER
|
|
96
|
+
collapse_object(object)
|
|
97
|
+
when Status::NO_CHANGE, Status::DROPPED
|
|
98
|
+
# nothing to do
|
|
99
|
+
else
|
|
100
|
+
msg = "Unexpected status #{s} for #{object} for schema collapsing"
|
|
101
|
+
raise AssumptionFailedError, msg
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Ensures inexistence of a single schema object
|
|
107
|
+
def collapse_object(object)
|
|
108
|
+
parent = object.parent
|
|
109
|
+
|
|
110
|
+
case status[parent]
|
|
111
|
+
when Status::DROPPED
|
|
112
|
+
# nothing do do, parent has certainly removed me
|
|
113
|
+
status[object] = Status::DROPPED
|
|
114
|
+
when Status::TO_DROP
|
|
115
|
+
#
|
|
116
|
+
# Delegate to parent if it needs to be collapsed itself
|
|
117
|
+
#
|
|
118
|
+
# Making this helps issuing a single DROP TABLE and avoiding
|
|
119
|
+
# many ALTER TABLE that will eventually fail (the last column)
|
|
120
|
+
#
|
|
121
|
+
collapse_object(parent)
|
|
122
|
+
status[object] = Status::DROPPED
|
|
123
|
+
else
|
|
124
|
+
status[object] = Status::PENDING
|
|
125
|
+
|
|
126
|
+
object.outside_dependents.each{|dep|
|
|
127
|
+
collapse_objects([ dep ])
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
collapse_call = :"collapse_#{object.builder_handler}"
|
|
131
|
+
self.send(collapse_call, object)
|
|
132
|
+
|
|
133
|
+
status[object] = Status::DROPPED
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Collapses a relation variable
|
|
138
|
+
def collapse_relvar(relvar)
|
|
139
|
+
script << Migrate::DropTable.new(relvar)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Collapses a candidate key
|
|
143
|
+
def collapse_candidate_key(ckey)
|
|
144
|
+
with_collapse_helper(ckey.relation_variable){|h| h.candidate_key(ckey)}
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Collapses a foreign key
|
|
148
|
+
def collapse_foreign_key(fkey)
|
|
149
|
+
with_collapse_helper(fkey.relation_variable){|h| h.foreign_key(fkey)}
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Collapses an attribute
|
|
153
|
+
def collapse_attribute(attribute)
|
|
154
|
+
with_collapse_helper(attribute.relation_variable){|h| h.attribute(attribute)}
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Collapses an index
|
|
158
|
+
def collapse_index(index)
|
|
159
|
+
with_collapse_helper(index.indexed_relvar){|h| h.index(index)}
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
############################################################################
|
|
163
|
+
### Expand algorithms (for alter/create)
|
|
164
|
+
############################################################################
|
|
165
|
+
|
|
166
|
+
# Yields the block with an helper to expand a relation
|
|
167
|
+
# variable, creating it if required
|
|
168
|
+
def with_expand_helper(rv)
|
|
169
|
+
if h = helpers[rv]
|
|
170
|
+
yield(h)
|
|
171
|
+
else
|
|
172
|
+
# create the operation
|
|
173
|
+
exists = relvar_exists?(rv)
|
|
174
|
+
h = exists ? Migrate::ExpandTable.new(rv) : Migrate::CreateTable.new(rv)
|
|
175
|
+
|
|
176
|
+
# execute sub operations and save
|
|
177
|
+
yield(helpers[rv] = h)
|
|
178
|
+
script << h
|
|
179
|
+
|
|
180
|
+
# assert that the table now exists
|
|
181
|
+
unless exists
|
|
182
|
+
relvar_exists!(rv)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# remove helper now
|
|
186
|
+
helpers.delete(rv)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Ensures existence of a list of schema objects.
|
|
191
|
+
def expand_objects(schema_objects)
|
|
192
|
+
schema_objects.each do |object|
|
|
193
|
+
case s = status[object]
|
|
194
|
+
when Status::TO_CREATE, Status::TO_ALTER
|
|
195
|
+
expand_object(object)
|
|
196
|
+
when Status::NO_CHANGE, Status::CREATED
|
|
197
|
+
# nothing do to
|
|
198
|
+
else
|
|
199
|
+
msg = "Unexpected status #{s} for #{object} for schema expansion"
|
|
200
|
+
raise AssumptionFailedError, msg
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Ensures existence of a single schema object
|
|
206
|
+
def expand_object(object)
|
|
207
|
+
parent = object.parent
|
|
208
|
+
|
|
209
|
+
if status[parent] == Status::TO_CREATE
|
|
210
|
+
#
|
|
211
|
+
# Delegate to parent if it needs to be ensured itself
|
|
212
|
+
#
|
|
213
|
+
# Making this helps issuing a single CREATE TABLE instead of
|
|
214
|
+
# many ALTER TABLE statements, which are not always supported
|
|
215
|
+
# by adapters.
|
|
216
|
+
#
|
|
217
|
+
expand_object(parent)
|
|
218
|
+
else
|
|
219
|
+
# Mark the object as being currently created
|
|
220
|
+
status[object] = Status::PENDING
|
|
221
|
+
|
|
222
|
+
# ensure dependencies
|
|
223
|
+
expand_objects(object.outside_dependencies)
|
|
224
|
+
|
|
225
|
+
# ensure itself and recurse on children
|
|
226
|
+
expand_call = :"expand_#{object.builder_handler}"
|
|
227
|
+
if object.composite?
|
|
228
|
+
# ensure composite objects
|
|
229
|
+
if self.respond_to?(expand_call)
|
|
230
|
+
self.send(expand_call, object){ expand_objects(object.parts) }
|
|
231
|
+
else
|
|
232
|
+
expand_objects(object.parts)
|
|
233
|
+
end
|
|
234
|
+
else
|
|
235
|
+
# ensure part objects
|
|
236
|
+
self.send(expand_call, object)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# mark object as ensured!
|
|
240
|
+
status[object] = Status::CREATED
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
### Composites
|
|
245
|
+
|
|
246
|
+
def expand_relvar_xxx(xxx)
|
|
247
|
+
with_expand_helper(rv = xxx.relation_variable){|helper| yield}
|
|
248
|
+
end
|
|
249
|
+
alias :expand_relvar :expand_relvar_xxx
|
|
250
|
+
alias :expand_heading :expand_relvar_xxx
|
|
251
|
+
|
|
252
|
+
### Parts
|
|
253
|
+
|
|
254
|
+
def expand_attribute(attribute)
|
|
255
|
+
with_expand_helper(rv = attribute.relation_variable){|helper|
|
|
256
|
+
helper.attribute(attribute)
|
|
257
|
+
}
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def expand_candidate_key(ckey)
|
|
261
|
+
with_expand_helper(rv = ckey.relation_variable){|helper|
|
|
262
|
+
helper.candidate_key(ckey)
|
|
263
|
+
}
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def expand_foreign_key(fkey)
|
|
267
|
+
with_expand_helper(rv = fkey.relation_variable){|helper|
|
|
268
|
+
helper.foreign_key(fkey)
|
|
269
|
+
}
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def expand_index(index)
|
|
273
|
+
with_expand_helper(rv = index.indexed_relvar){|helper|
|
|
274
|
+
helper.index(index)
|
|
275
|
+
}
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
end # class Stager
|
|
279
|
+
end # module Migrate
|
|
280
|
+
end # module Schema
|
|
281
|
+
end # module Core
|
|
282
|
+
end # module DbAgile
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module DbAgile
|
|
2
|
+
module Core
|
|
3
|
+
module Schema
|
|
4
|
+
class Part < SchemaObject
|
|
5
|
+
|
|
6
|
+
# Object name
|
|
7
|
+
attr_reader :name
|
|
8
|
+
|
|
9
|
+
# Object definition
|
|
10
|
+
attr_reader :definition
|
|
11
|
+
|
|
12
|
+
# Creates a part instance
|
|
13
|
+
def initialize(name, definition)
|
|
14
|
+
@name = name
|
|
15
|
+
@definition = definition
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Makes a sanity check on the part
|
|
19
|
+
def _sanity_check(schema)
|
|
20
|
+
raise SchemaInternalError, "No name provided on #{self}" if name.nil?
|
|
21
|
+
raise SchemaInternalError, "No definition provided on #{self}" if definition.nil?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Checks this composite's semantics and collect errors
|
|
25
|
+
def _semantics_check(clazz, buffer)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
############################################################################
|
|
29
|
+
### Schema typing
|
|
30
|
+
############################################################################
|
|
31
|
+
|
|
32
|
+
# Returns true if this object is a logical object, false otherwise
|
|
33
|
+
def logical?
|
|
34
|
+
relvar? or attribute? or constraint?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns true if this object is a relation variable, false otherwise
|
|
38
|
+
def relvar?
|
|
39
|
+
self.kind_of?(Schema::Logical::Relvar)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns true if this object is an attribute, false otherwise
|
|
43
|
+
def attribute?
|
|
44
|
+
self.kind_of?(Schema::Logical::Attribute)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns true if this object is a constraint, false otherwise
|
|
48
|
+
def constraint?
|
|
49
|
+
self.kind_of?(Schema::Logical::Constraint)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns true if this object is a candidate key, false otherwise
|
|
53
|
+
def candidate_key?
|
|
54
|
+
self.kind_of?(Schema::Logical::Constraint::CandidateKey)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns true if this object is a primary key, false otherwise
|
|
58
|
+
def primary_key?
|
|
59
|
+
self.candidate_key? and self.primary?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns true if this object is a foreign key, false otherwise
|
|
63
|
+
def foreign_key?
|
|
64
|
+
self.kind_of?(Schema::Logical::Constraint::ForeignKey)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns true if this object is a physical object, false otherwise
|
|
68
|
+
def physical?
|
|
69
|
+
index?
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns true if this object is an index, false otherwise
|
|
73
|
+
def index?
|
|
74
|
+
self.kind_of?(Schema::Physical::Index)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
############################################################################
|
|
78
|
+
### Schema::SchemaObject
|
|
79
|
+
############################################################################
|
|
80
|
+
|
|
81
|
+
# Returns an array with part dependencies
|
|
82
|
+
def dependencies(include_parent = false)
|
|
83
|
+
include_parent ? [ parent ] : []
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @see DbAgile::Core::Schema
|
|
87
|
+
def visit(&block)
|
|
88
|
+
block.call(self, parent)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
############################################################################
|
|
92
|
+
### Equality and hash code
|
|
93
|
+
############################################################################
|
|
94
|
+
|
|
95
|
+
# Compares with another part
|
|
96
|
+
def look_same_as?(other)
|
|
97
|
+
return nil unless other.kind_of?(self.class)
|
|
98
|
+
(name == other.name) and (definition == other.definition)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Duplicates this part
|
|
102
|
+
def dup
|
|
103
|
+
self.class.new(name, definition.dup)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Returns a string representation
|
|
107
|
+
def to_s
|
|
108
|
+
"#{DbAgile::RubyTools::unqualified_class_name(self.class)}: #{name} #{definition.inspect}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end # class Part
|
|
112
|
+
end # module Schema
|
|
113
|
+
end # module Core
|
|
114
|
+
end # module DbAgile
|