dbagile 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/dbagile.rb +2 -2
- data/lib/dbagile/adapter/sequel/data/transaction_driven.rb +1 -0
- data/lib/dbagile/adapter/sequel/schema/concrete_script.rb +18 -0
- data/lib/dbagile/adapter/sequel/schema/table_driven.rb +10 -1
- data/lib/dbagile/adapter/sequel/sequel_tracer.rb +1 -0
- data/lib/dbagile/command/bulk/commons.rb +7 -2
- data/lib/dbagile/command/bulk/export.rb +4 -1
- data/lib/dbagile/command/bulk/import.rb +32 -2
- data/lib/dbagile/command/schema/check.rb +2 -1
- data/lib/dbagile/command/schema/commons.rb +16 -1
- data/lib/dbagile/command/schema/dump.rb +85 -4
- data/lib/dbagile/command/schema/sql_script.rb +1 -0
- data/lib/dbagile/contract/data/dataset.rb +9 -0
- data/lib/dbagile/core/schema/builder.rb +8 -4
- data/lib/dbagile/core/schema/builder/concept_factory.rb +5 -0
- data/lib/dbagile/core/schema/composite.rb +1 -1
- data/lib/dbagile/core/schema/computations/merge.rb +1 -1
- data/lib/dbagile/core/schema/errors.rb +1 -3
- data/lib/dbagile/core/schema/logical.rb +1 -0
- data/lib/dbagile/core/schema/logical/attribute.rb +11 -2
- data/lib/dbagile/core/schema/logical/relview.rb +42 -0
- data/lib/dbagile/core/schema/migrate/abstract_script.rb +2 -0
- data/lib/dbagile/core/schema/migrate/create_view.rb +15 -0
- data/lib/dbagile/core/schema/migrate/drop_view.rb +15 -0
- data/lib/dbagile/core/schema/migrate/operation.rb +8 -6
- data/lib/dbagile/core/schema/migrate/stager.rb +12 -3
- data/lib/dbagile/core/schema/part.rb +0 -49
- data/lib/dbagile/core/schema/schema_object.rb +54 -0
- data/lib/dbagile/environment/repository.rb +2 -2
- data/lib/dbagile/errors.rb +3 -0
- data/lib/dbagile/io.rb +7 -3
- data/lib/dbagile/io/html.rb +48 -0
- data/lib/dbagile/restful.rb +1 -1
- data/lib/dbagile/restful/middleware/one_database.rb +1 -0
- data/lib/dbagile/restful/middleware/post.rb +16 -1
- data/lib/dbagile/tools/tuple.rb +7 -0
- data/test/assumptions/sequel/connect.spec +12 -9
- data/test/assumptions/sequel/test.db +0 -0
- data/test/commands.spec +4 -4
- data/test/commands/bulk/import.spec +26 -3
- data/test/commands/schema/check.spec +20 -13
- data/test/commands/schema/dump.spec +23 -0
- data/test/fixtures/basics/dbagile.idx +7 -7
- data/test/fixtures/basics/robust.db +0 -0
- data/test/fixtures/basics/test.db +0 -0
- data/test/fixtures/empty/dbagile.idx +1 -1
- data/test/restful/get/html_format.ex +12 -0
- data/test/run_all_suite.rb +1 -1
- data/test/spec_helper.rb +0 -2
- data/test/support/be_a_valid_json_string.rb +1 -1
- data/test/support/be_a_valid_yaml_string.rb +1 -1
- data/test/unit/core/schema/fixtures/views.yaml +5 -0
- data/test/unit/core/schema/part_keys.spec +12 -0
- data/test/unit/core/schema/yaml_load.spec +5 -0
- metadata +414 -244
@@ -102,13 +102,11 @@ module DbAgile
|
|
102
102
|
TargetKeyMismatch
|
103
103
|
]
|
104
104
|
MESSAGE_VALUES = [
|
105
|
-
'invalid default value on
|
105
|
+
'invalid default value \'#{schema_object.default_value}\' on #{schema_object}',
|
106
106
|
'relvar #{schema_object.relation_variable.name} has an empty heading (unsupported so far)',
|
107
107
|
'relvar #{schema_object.name} has no primary key',
|
108
108
|
'invalid constraint #{schema_object.name} on #{schema_object.relation_variable.name}',
|
109
|
-
|
110
109
|
'invalid index #{schema_object.name}',
|
111
|
-
|
112
110
|
'no such relvar #{args[:relvar_name]}',
|
113
111
|
'no such attributes #{args[:attributes].join(\',\')}',
|
114
112
|
'no such candidate key #{args[:constraint_name]}',
|
@@ -18,6 +18,7 @@ module DbAgile
|
|
18
18
|
end # module Core
|
19
19
|
end # module DbAgile
|
20
20
|
require 'dbagile/core/schema/logical/relvar'
|
21
|
+
require 'dbagile/core/schema/logical/relview'
|
21
22
|
require 'dbagile/core/schema/logical/heading'
|
22
23
|
require 'dbagile/core/schema/logical/attribute'
|
23
24
|
require 'dbagile/core/schema/logical/constraints'
|
@@ -22,6 +22,10 @@ module DbAgile
|
|
22
22
|
def mandatory?
|
23
23
|
!(definition[:mandatory] == false)
|
24
24
|
end
|
25
|
+
|
26
|
+
def relvar
|
27
|
+
parent.parent
|
28
|
+
end
|
25
29
|
|
26
30
|
############################################################################
|
27
31
|
### Dependency control
|
@@ -38,7 +42,7 @@ module DbAgile
|
|
38
42
|
|
39
43
|
# @see DbAgile::Core::Schema::SchemaObject
|
40
44
|
def _semantics_check(clazz, buffer)
|
41
|
-
unless default_value.nil? or
|
45
|
+
unless default_value.nil? or (domain === default_value)
|
42
46
|
buffer.add_error(self, clazz::InvalidDefaultValue)
|
43
47
|
end
|
44
48
|
end
|
@@ -54,13 +58,18 @@ module DbAgile
|
|
54
58
|
out.map("tag:yaml.org,2002:map", :inline ) do |map|
|
55
59
|
map.add('domain', defn[:domain].to_s)
|
56
60
|
map.add('mandatory', false) unless defn[:mandatory]
|
57
|
-
|
61
|
+
unless defn[:default].nil?
|
58
62
|
map.add('default', defn[:default])
|
59
63
|
end
|
60
64
|
end
|
61
65
|
}
|
62
66
|
end
|
63
67
|
|
68
|
+
# Returns a string representation
|
69
|
+
def to_s
|
70
|
+
"Attribute #{relvar.name}::#{name} #{definition.inspect}"
|
71
|
+
end
|
72
|
+
|
64
73
|
end # class Attribute
|
65
74
|
end # module Logical
|
66
75
|
end # module Schema
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module DbAgile
|
2
|
+
module Core
|
3
|
+
module Schema
|
4
|
+
class Logical
|
5
|
+
class Relview < Schema::Part
|
6
|
+
|
7
|
+
############################################################################
|
8
|
+
### Dependency control
|
9
|
+
############################################################################
|
10
|
+
|
11
|
+
# @see DbAgile::Core::Schema::SchemaObject
|
12
|
+
def dependencies(include_parent = false)
|
13
|
+
include_parent ? [ parent ] : []
|
14
|
+
end
|
15
|
+
|
16
|
+
############################################################################
|
17
|
+
### Check interface
|
18
|
+
############################################################################
|
19
|
+
|
20
|
+
# @see DbAgile::Core::Schema::SchemaObject
|
21
|
+
def _semantics_check(clazz, buffer)
|
22
|
+
end
|
23
|
+
|
24
|
+
############################################################################
|
25
|
+
### About IO
|
26
|
+
############################################################################
|
27
|
+
|
28
|
+
# Delegation pattern on YAML flushing
|
29
|
+
def to_yaml(opts = {})
|
30
|
+
definition.to_yaml(opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a string representation
|
34
|
+
def to_s
|
35
|
+
"Relview #{name} #{definition.inspect}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end # class Relview
|
39
|
+
end # module Logical
|
40
|
+
end # module Schema
|
41
|
+
end # module Core
|
42
|
+
end # module DbAgile
|
@@ -33,3 +33,5 @@ require 'dbagile/core/schema/migrate/create_table'
|
|
33
33
|
require 'dbagile/core/schema/migrate/drop_table'
|
34
34
|
require 'dbagile/core/schema/migrate/expand_table'
|
35
35
|
require 'dbagile/core/schema/migrate/collapse_table'
|
36
|
+
require 'dbagile/core/schema/migrate/create_view'
|
37
|
+
require 'dbagile/core/schema/migrate/drop_view'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DbAgile
|
2
|
+
module Core
|
3
|
+
module Schema
|
4
|
+
module Migrate
|
5
|
+
class CreateView < Migrate::Operation
|
6
|
+
|
7
|
+
def to_sql92
|
8
|
+
"CREATE VIEW #{table_name} (#{relvar.definition})"
|
9
|
+
end
|
10
|
+
|
11
|
+
end # class CreateView
|
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 DropView < Migrate::Operation
|
6
|
+
|
7
|
+
def to_sql92
|
8
|
+
"DROP VIEW #{table_name}"
|
9
|
+
end
|
10
|
+
|
11
|
+
end # class DropView
|
12
|
+
end # module Migrate
|
13
|
+
end # module Schema
|
14
|
+
end # module Core
|
15
|
+
end # module DbAgile
|
@@ -7,19 +7,21 @@ module DbAgile
|
|
7
7
|
# The sub operations
|
8
8
|
attr_reader :operations
|
9
9
|
|
10
|
-
# Targetted relation variable
|
11
|
-
attr_reader :
|
10
|
+
# Targetted relation variable/view
|
11
|
+
attr_reader :rel_object
|
12
|
+
alias :relvar :rel_object
|
13
|
+
alias :relview :rel_object
|
12
14
|
|
13
15
|
# Returns table name
|
14
16
|
def table_name
|
15
17
|
relvar.name
|
16
18
|
end
|
17
19
|
|
18
|
-
def initialize(
|
19
|
-
unless relvar.
|
20
|
-
raise ArgumentError, "Relvar expected for
|
20
|
+
def initialize(rel_object)
|
21
|
+
unless rel_object.relvar? or rel_object.relview?
|
22
|
+
raise ArgumentError, "Relvar expected for rel_object, got #{rel_object.class}"
|
21
23
|
end
|
22
|
-
@
|
24
|
+
@rel_object = rel_object
|
23
25
|
@operations = []
|
24
26
|
end
|
25
27
|
|
@@ -139,6 +139,11 @@ module DbAgile
|
|
139
139
|
script << Migrate::DropTable.new(relvar)
|
140
140
|
end
|
141
141
|
|
142
|
+
# Collapses a relation view
|
143
|
+
def collapse_relview(relview)
|
144
|
+
script << Migrate::DropView.new(relview)
|
145
|
+
end
|
146
|
+
|
142
147
|
# Collapses a candidate key
|
143
148
|
def collapse_candidate_key(ckey)
|
144
149
|
with_collapse_helper(ckey.relation_variable){|h| h.candidate_key(ckey)}
|
@@ -172,16 +177,16 @@ module DbAgile
|
|
172
177
|
# create the operation
|
173
178
|
exists = relvar_exists?(rv)
|
174
179
|
h = exists ? Migrate::ExpandTable.new(rv) : Migrate::CreateTable.new(rv)
|
175
|
-
|
180
|
+
|
176
181
|
# execute sub operations and save
|
177
182
|
yield(helpers[rv] = h)
|
178
183
|
script << h
|
179
|
-
|
184
|
+
|
180
185
|
# assert that the table now exists
|
181
186
|
unless exists
|
182
187
|
relvar_exists!(rv)
|
183
188
|
end
|
184
|
-
|
189
|
+
|
185
190
|
# remove helper now
|
186
191
|
helpers.delete(rv)
|
187
192
|
end
|
@@ -248,6 +253,10 @@ module DbAgile
|
|
248
253
|
end
|
249
254
|
alias :expand_relvar :expand_relvar_xxx
|
250
255
|
alias :expand_heading :expand_relvar_xxx
|
256
|
+
|
257
|
+
def expand_relview(rv)
|
258
|
+
script << Migrate::CreateView.new(rv)
|
259
|
+
end
|
251
260
|
|
252
261
|
### Parts
|
253
262
|
|
@@ -25,55 +25,6 @@ module DbAgile
|
|
25
25
|
def _semantics_check(clazz, buffer)
|
26
26
|
end
|
27
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
28
|
############################################################################
|
78
29
|
### Schema::SchemaObject
|
79
30
|
############################################################################
|
@@ -25,6 +25,60 @@ module DbAgile
|
|
25
25
|
end
|
26
26
|
alias :terminal? :part?
|
27
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 relview? or attribute? or constraint?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns true if this object is a relation view, false otherwise
|
38
|
+
def relview?
|
39
|
+
self.kind_of?(Schema::Logical::Relview)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns true if this object is a relation variable, false otherwise
|
43
|
+
def relvar?
|
44
|
+
self.kind_of?(Schema::Logical::Relvar)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns true if this object is an attribute, false otherwise
|
48
|
+
def attribute?
|
49
|
+
self.kind_of?(Schema::Logical::Attribute)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns true if this object is a constraint, false otherwise
|
53
|
+
def constraint?
|
54
|
+
self.kind_of?(Schema::Logical::Constraint)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns true if this object is a candidate key, false otherwise
|
58
|
+
def candidate_key?
|
59
|
+
self.kind_of?(Schema::Logical::CandidateKey)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns true if this object is a primary key, false otherwise
|
63
|
+
def primary_key?
|
64
|
+
self.candidate_key? and self.primary?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns true if this object is a foreign key, false otherwise
|
68
|
+
def foreign_key?
|
69
|
+
self.kind_of?(Schema::Logical::ForeignKey)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns true if this object is a physical object, false otherwise
|
73
|
+
def physical?
|
74
|
+
index?
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns true if this object is an index, false otherwise
|
78
|
+
def index?
|
79
|
+
self.kind_of?(Schema::Physical::Index)
|
80
|
+
end
|
81
|
+
|
28
82
|
############################################################################
|
29
83
|
### Schema hierarchy
|
30
84
|
############################################################################
|
@@ -118,7 +118,7 @@ module DbAgile
|
|
118
118
|
def with_current_database
|
119
119
|
raise ArgumentError, "Missing block" unless block_given?
|
120
120
|
db = repository.current_database
|
121
|
-
raise NoDefaultDatabaseError if db.nil?
|
121
|
+
raise DbAgile::NoDefaultDatabaseError, "No default database set (try 'dba use ...' first)" if db.nil?
|
122
122
|
yield(db)
|
123
123
|
end
|
124
124
|
|
@@ -140,7 +140,7 @@ module DbAgile
|
|
140
140
|
raise ArgumentError, "Invalid database name #{db}"
|
141
141
|
end
|
142
142
|
raise NoSuchDatabaseError if db.nil?
|
143
|
-
db.with_connection(&block)
|
143
|
+
db.with_connection(conn_options, &block)
|
144
144
|
end
|
145
145
|
|
146
146
|
#
|
data/lib/dbagile/errors.rb
CHANGED
@@ -27,4 +27,7 @@ module DbAgile
|
|
27
27
|
# Raised when usage of schema files fails because they are not installed
|
28
28
|
class NoSchemaFilesError < DbAgile::Error; end
|
29
29
|
|
30
|
+
# Raised when a candidate key cannot be infered from a given tuple
|
31
|
+
class CandidateKeyNotFoundError < DbAgile::Error; end
|
32
|
+
|
30
33
|
end # module DbAgile
|
data/lib/dbagile/io.rb
CHANGED
@@ -4,6 +4,7 @@ require 'dbagile/io/csv'
|
|
4
4
|
require 'dbagile/io/json'
|
5
5
|
require 'dbagile/io/yaml'
|
6
6
|
require 'dbagile/io/xml'
|
7
|
+
require 'dbagile/io/html'
|
7
8
|
require 'dbagile/io/ruby'
|
8
9
|
require 'dbagile/io/text'
|
9
10
|
module DbAgile
|
@@ -15,10 +16,10 @@ module DbAgile
|
|
15
16
|
}
|
16
17
|
|
17
18
|
# Known IO formats
|
18
|
-
KNOWN_FORMATS = [:yaml, :csv, :json, :ruby, :text, :xml]
|
19
|
+
KNOWN_FORMATS = [:yaml, :csv, :json, :ruby, :text, :xml, :html]
|
19
20
|
|
20
21
|
# Known to_xxx IO formats
|
21
|
-
KNOWN_TO_FORMATS = [:yaml, :csv, :json, :ruby, :text, :xml]
|
22
|
+
KNOWN_TO_FORMATS = [:yaml, :csv, :json, :ruby, :text, :xml, :html]
|
22
23
|
|
23
24
|
# Known from_xxx formats
|
24
25
|
KNOWN_FROM_FORMATS = [:yaml, :csv, :json, :ruby]
|
@@ -30,7 +31,8 @@ module DbAgile
|
|
30
31
|
:json => DbAgile::IO::JSON,
|
31
32
|
:ruby => DbAgile::IO::Ruby,
|
32
33
|
:text => DbAgile::IO::Text,
|
33
|
-
:xml => DbAgile::IO::XML
|
34
|
+
:xml => DbAgile::IO::XML,
|
35
|
+
:html => DbAgile::IO::HTML
|
34
36
|
}
|
35
37
|
|
36
38
|
# Which format for what extension
|
@@ -41,6 +43,7 @@ module DbAgile
|
|
41
43
|
".yaml" => :yaml,
|
42
44
|
".yml" => :yaml,
|
43
45
|
".xml" => :xml,
|
46
|
+
".html" => :html,
|
44
47
|
".ruby" => :ruby,
|
45
48
|
".rb" => :ruby
|
46
49
|
}
|
@@ -52,6 +55,7 @@ module DbAgile
|
|
52
55
|
:json => "application/json",
|
53
56
|
:yaml => "text/yaml",
|
54
57
|
:xml => "text/xml",
|
58
|
+
:html => "text/html",
|
55
59
|
:ruby => "text/plain"
|
56
60
|
}
|
57
61
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "cgi"
|
2
|
+
module DbAgile
|
3
|
+
module IO
|
4
|
+
module HTML
|
5
|
+
|
6
|
+
DEFAULT_OPTIONS = { }
|
7
|
+
|
8
|
+
def with_tag(tag, buffer, indent = 0)
|
9
|
+
buffer << " "*indent << "<#{tag}>\n"
|
10
|
+
yield
|
11
|
+
buffer << " "*indent << "</#{tag}>\n"
|
12
|
+
end
|
13
|
+
module_function :with_tag
|
14
|
+
|
15
|
+
#
|
16
|
+
# Outputs some data as an HTML string
|
17
|
+
#
|
18
|
+
# @return [...] the buffer itself
|
19
|
+
#
|
20
|
+
def to_html(data, columns = nil, buffer = "", options = {})
|
21
|
+
options = DEFAULT_OPTIONS.merge(options)
|
22
|
+
with_tag("table", buffer, 0) {
|
23
|
+
with_tag("thead", buffer, 1) {
|
24
|
+
with_tag("tr", buffer, 2) {
|
25
|
+
columns.each{|column|
|
26
|
+
buffer << " "*3 << "<td>#{CGI::escape(column.to_s)}</td>\n"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
with_tag("tbody", buffer, 1) {
|
31
|
+
data.each{|row|
|
32
|
+
with_tag("tr", buffer, 2) {
|
33
|
+
columns.each{|column|
|
34
|
+
value = row[column]
|
35
|
+
cssclazz = value.class.name.to_s.downcase
|
36
|
+
buffer << " "*3 << "<td class=\"#{cssclazz}\">#{CGI::escapeHTML(value.to_s)}</td>\n"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
buffer
|
43
|
+
end
|
44
|
+
module_function :to_html
|
45
|
+
|
46
|
+
end # module HTML
|
47
|
+
end # module IO
|
48
|
+
end # module DbAgile
|