activefacts-compositions 1.9.8 → 1.9.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/activefacts-compositions.gemspec +1 -1
- data/bin/schema_compositor +67 -62
- data/lib/activefacts/compositions/datavault.rb +23 -39
- data/lib/activefacts/compositions/relational.rb +81 -14
- data/lib/activefacts/compositions/staging.rb +49 -0
- data/lib/activefacts/compositions/version.rb +1 -1
- data/lib/activefacts/generator/doc/cwm.rb +80 -302
- data/lib/activefacts/generator/doc/glossary.rb +1 -2
- data/lib/activefacts/generator/doc/graphviz.rb +3 -3
- data/lib/activefacts/generator/doc/ldm.rb +39 -39
- data/lib/activefacts/generator/oo.rb +3 -3
- data/lib/activefacts/generator/rails/models.rb +4 -4
- data/lib/activefacts/generator/rails/schema.rb +56 -25
- data/lib/activefacts/generator/ruby.rb +2 -1
- data/lib/activefacts/generator/sql.rb +4 -3
- data/lib/activefacts/generator/sql/server.rb +0 -1
- data/lib/activefacts/generator/summary.rb +3 -3
- data/lib/activefacts/generator/validate.rb +3 -3
- data/lib/activefacts/loadable.rb +3 -3
- metadata +5 -4
@@ -0,0 +1,49 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Compositions, Staging Compositor.
|
3
|
+
#
|
4
|
+
# Computes a Staging schema for Data Vault.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2016 Graeme Port. Read the LICENSE file.
|
7
|
+
#
|
8
|
+
require "activefacts/compositions/relational"
|
9
|
+
|
10
|
+
module ActiveFacts
|
11
|
+
module Compositions
|
12
|
+
class Staging < Relational
|
13
|
+
public
|
14
|
+
def self.options
|
15
|
+
{
|
16
|
+
stgname: ['String', "Suffix or pattern for naming staging tables. Include a + to insert the name. Default 'STG'"],
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize constellation, name, options = {}
|
21
|
+
# Extract recognised options:
|
22
|
+
@option_stg_name = options.delete('stgname') || 'STG'
|
23
|
+
@option_stg_name.sub!(/^/,'+ ') unless @option_stg_name =~ /\+/
|
24
|
+
|
25
|
+
super constellation, name, options
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def inject_all_datetime_recordsource
|
30
|
+
composites = @composition.all_composite.to_a
|
31
|
+
return if composites.empty?
|
32
|
+
|
33
|
+
trace :staging, "Injecting load datetime and record source" do
|
34
|
+
@composition.all_composite.each do |composite|
|
35
|
+
inject_datetime_recordsource composite.mapping
|
36
|
+
composite.mapping.re_rank
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def devolve_all
|
42
|
+
# Rename composites with STG prefix
|
43
|
+
rename_parents
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
publish_compositor(Staging)
|
48
|
+
end
|
49
|
+
end
|
@@ -8,7 +8,6 @@
|
|
8
8
|
require 'digest/sha1'
|
9
9
|
require 'activefacts/metamodel'
|
10
10
|
require 'activefacts/metamodel/datatypes'
|
11
|
-
require 'activefacts/registry'
|
12
11
|
require 'activefacts/compositions'
|
13
12
|
require 'activefacts/generator'
|
14
13
|
require 'activefacts/support'
|
@@ -39,6 +38,11 @@ module ActiveFacts
|
|
39
38
|
attr_accessor :xmiid
|
40
39
|
end
|
41
40
|
|
41
|
+
class ActiveFacts::Metamodel::ValueField
|
42
|
+
attr_accessor :xmiid
|
43
|
+
attr_accessor :index_xmiid
|
44
|
+
end
|
45
|
+
|
42
46
|
class CWM
|
43
47
|
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
44
48
|
def self.options
|
@@ -47,25 +51,26 @@ module ActiveFacts
|
|
47
51
|
}
|
48
52
|
end
|
49
53
|
|
50
|
-
def initialize
|
51
|
-
|
54
|
+
def initialize compositions, options = {}
|
55
|
+
raise "--cwm only processes a single composition" if compositions.size > 1
|
56
|
+
@composition = compositions[0]
|
52
57
|
@options = options
|
53
58
|
@underscore = options.has_key?("underscore") ? (options['underscore'] || '_') : ''
|
54
|
-
|
59
|
+
|
55
60
|
@vocabulary = composition.constellation.Vocabulary.values[0] # REVISIT when importing from other vocabularies
|
56
61
|
end
|
57
62
|
|
58
63
|
def data_type_context
|
59
64
|
@data_type_context ||= CWMDataTypeContext.new
|
60
65
|
end
|
61
|
-
|
66
|
+
|
62
67
|
def generate
|
63
68
|
# @tables_emitted = {}
|
64
|
-
@
|
69
|
+
@ns = 0
|
65
70
|
@datatypes = Array.new
|
66
|
-
|
71
|
+
|
67
72
|
trace.enable 'cwm'
|
68
|
-
|
73
|
+
|
69
74
|
model_ns, schema_ns = populate_namespace_ids
|
70
75
|
|
71
76
|
generate_header +
|
@@ -108,16 +113,22 @@ module ActiveFacts
|
|
108
113
|
def indent depth, str
|
109
114
|
" " * depth + str + "\n"
|
110
115
|
end
|
111
|
-
|
112
|
-
def
|
113
|
-
ns
|
114
|
-
@
|
115
|
-
ns
|
116
|
+
|
117
|
+
def rawnsdef
|
118
|
+
@ns += 1
|
119
|
+
"_#{@ns}"
|
116
120
|
end
|
117
|
-
|
121
|
+
|
122
|
+
def nsdef obj, pref = nil
|
123
|
+
if obj.xmiid == nil
|
124
|
+
obj.xmiid = "#{pref}#{rawnsdef}"
|
125
|
+
end
|
126
|
+
obj.xmiid
|
127
|
+
end
|
128
|
+
|
118
129
|
def populate_namespace_ids
|
119
|
-
model_ns =
|
120
|
-
schema_ns =
|
130
|
+
model_ns = rawnsdef
|
131
|
+
schema_ns = rawnsdef
|
121
132
|
|
122
133
|
@composition.
|
123
134
|
all_composite.
|
@@ -129,21 +140,18 @@ module ActiveFacts
|
|
129
140
|
|
130
141
|
def populate_table_ids(table)
|
131
142
|
tname = table_name(table)
|
132
|
-
|
143
|
+
nsdef(table)
|
133
144
|
table.mapping.all_leaf.flat_map do |leaf|
|
134
145
|
# Absorbed empty subtypes appear as leaves
|
135
146
|
next if leaf.is_a?(MM::Absorption) && leaf.parent_role.fact_type.is_a?(MM::TypeInheritance)
|
136
|
-
|
147
|
+
nsdef(leaf)
|
137
148
|
end
|
138
149
|
table.all_index.map do |index|
|
139
|
-
|
140
|
-
|
141
|
-
if index.all_index_field.size == 1
|
142
|
-
index.all_index_field[0].component.index_xmiid = index.xmiid
|
143
|
-
end
|
150
|
+
nsdef(index)
|
151
|
+
index.all_index_field.map{|idf| idf.component.index_xmiid = index.xmiid}
|
144
152
|
end
|
145
|
-
table.all_foreign_key_as_source_composite.map do |fk|
|
146
|
-
|
153
|
+
table.all_foreign_key_as_source_composite.sort_by{|fk| [fk.source_composite.mapping.name, fk.absorption.inspect] }.map do |fk|
|
154
|
+
nsdef(fk)
|
147
155
|
end
|
148
156
|
end
|
149
157
|
|
@@ -209,7 +217,7 @@ module ActiveFacts
|
|
209
217
|
|
210
218
|
table_columns =
|
211
219
|
indent(depth, " <CWM:Classifier.feature>") +
|
212
|
-
(table.mapping.all_leaf.flat_map do |leaf|
|
220
|
+
(table.mapping.all_leaf.flat_map.sort_by{|c| column_name(c)}.map do |leaf|
|
213
221
|
# Absorbed empty subtypes appear as leaves
|
214
222
|
next if leaf.is_a?(MM::Absorption) && leaf.parent_role.fact_type.is_a?(MM::TypeInheritance)
|
215
223
|
|
@@ -221,10 +229,10 @@ module ActiveFacts
|
|
221
229
|
table_keys =
|
222
230
|
indent(depth, " <CWM:Namespace.ownedElement>") +
|
223
231
|
(table.all_index.map do |index|
|
224
|
-
generate_index(depth+2, table.xmiid, index, name)
|
232
|
+
generate_index(depth+2, table.xmiid, index, name, table.all_foreign_key_as_target_composite)
|
225
233
|
end
|
226
234
|
) * "" +
|
227
|
-
(table.all_foreign_key_as_source_composite.map do |fk|
|
235
|
+
(table.all_foreign_key_as_source_composite.sort_by{|fk| [fk.source_composite.mapping.name, fk.absorption.inspect] }.map do |fk|
|
228
236
|
generate_foreign_key(depth+2, table.xmiid, fk)
|
229
237
|
end
|
230
238
|
) * "" +
|
@@ -256,7 +264,7 @@ module ActiveFacts
|
|
256
264
|
end
|
257
265
|
|
258
266
|
def create_data_type(type_name, type_num, type_params)
|
259
|
-
type_ns =
|
267
|
+
type_ns = rawnsdef
|
260
268
|
|
261
269
|
cwm_data_type =
|
262
270
|
"<CWMRDB:SQLSimpleType xmi.id=\"#{type_ns}\" name=\"#{type_name}\" visibility=\"public\" typeNumber=\"#{type_num}\" #{type_params}/>"
|
@@ -265,7 +273,7 @@ module ActiveFacts
|
|
265
273
|
type_ns
|
266
274
|
end
|
267
275
|
|
268
|
-
def generate_index(depth, table_ns, index, table_name)
|
276
|
+
def generate_index(depth, table_ns, index, table_name, all_fks_as_target)
|
269
277
|
key_ns = index.xmiid
|
270
278
|
|
271
279
|
nullable_columns =
|
@@ -276,25 +284,42 @@ module ActiveFacts
|
|
276
284
|
|
277
285
|
primary = index.composite_as_primary_index && !contains_nullable_columns
|
278
286
|
column_ids =
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
clustering =
|
283
|
-
|
287
|
+
index.all_index_field.map do |ixf|
|
288
|
+
ixf.component.xmiid
|
289
|
+
end
|
290
|
+
# clustering =
|
291
|
+
# (index.composite_as_primary_index ? ' CLUSTERED' : ' NONCLUSTERED')
|
284
292
|
|
285
|
-
key_type = primary ? 'PrimaryKey' : 'UniqueKey'
|
293
|
+
key_type = primary ? 'CWMRDB:PrimaryKey' : 'CWM:UniqueKey'
|
294
|
+
|
295
|
+
# find target foreign keys for this index
|
296
|
+
fks_as_target = all_fks_as_target
|
286
297
|
|
287
|
-
if column_ids.count == 1
|
298
|
+
if column_ids.count == 1 && fks_as_target.count == 0
|
288
299
|
colid = column_ids[0]
|
289
|
-
indent(depth, "
|
300
|
+
indent(depth, "<#{key_type} xmi.id=\"#{key_ns}\" name=\"XPK#{table_name}\" visibility=\"public\" namespace=\"#{table_ns}\" feature=\"#{colid}\"/>")
|
290
301
|
else
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
302
|
+
if column_ids.count == 1
|
303
|
+
colid = column_ids[0]
|
304
|
+
indent(depth, "<#{key_type} xmi.id=\"#{key_ns}\" name=\"XPK#{table_name}\" visibility=\"public\" namespace=\"#{table_ns}\" feature=\"#{colid}\">")
|
305
|
+
else
|
306
|
+
indent(depth, "<#{key_type} xmi.id=\"#{key_ns}\" name=\"XPK#{table_name}\" visibility=\"public\" namespace=\"#{table_ns}\">") +
|
307
|
+
indent(depth, " <CWM:UniqueKey.feature>") +
|
308
|
+
column_ids.map do |id|
|
309
|
+
indent(depth, " <CWM:StructuralFeature xmi.idref=\"#{id}\"/>")
|
310
|
+
end * "" +
|
311
|
+
indent(depth, " </CWM:UniqueKey.feature>")
|
312
|
+
end +
|
313
|
+
if fks_as_target.count > 0
|
314
|
+
indent(depth, "<CWM:UniqueKey.keyRelationship>") +
|
315
|
+
fks_as_target.map do |fk|
|
316
|
+
indent(depth, " <CWM:KeyRelationship xmi.idref=\"#{fk.xmiid}\"/>")
|
317
|
+
end * "" +
|
318
|
+
indent(depth, "</CWM:UniqueKey.keyRelationship>")
|
319
|
+
else
|
320
|
+
""
|
321
|
+
end +
|
322
|
+
indent(depth, "</#{key_type}>")
|
298
323
|
end
|
299
324
|
end
|
300
325
|
|
@@ -304,13 +329,19 @@ module ActiveFacts
|
|
304
329
|
if fk.all_foreign_key_field.size == 1
|
305
330
|
fkf = fk.all_foreign_key_field[0]
|
306
331
|
ixf = fk.all_index_field[0]
|
307
|
-
indent(depth, "<CWMRDB:ForeignKey xmi.id=\"#{key_ns}\" name=\"R#{key_ns}\" visibility=\"public\" namespace=\"#{table_ns}\" feature=\"#{fkf.component.xmiid}\" uniqueKey=\"#{ixf.component.index_xmiid}\"/>")
|
332
|
+
indent(depth, "<CWMRDB:ForeignKey xmi.id=\"#{key_ns}\" name=\"R#{key_ns}\" visibility=\"public\" namespace=\"#{table_ns}\" feature=\"#{fkf.component.xmiid}\" uniqueKey=\"#{ixf.component.index_xmiid}\" />")
|
308
333
|
else
|
309
334
|
indent(depth, "<CWMRDB:ForeignKey xmi.id=\"#{key_ns}\" name=\"R#{key_ns}\" visibility=\"public\" namespace=\"#{table_ns}\">") +
|
310
335
|
indent(depth, " <CWM:KeyRelationship.feature>") +
|
311
|
-
|
312
|
-
|
313
|
-
|
336
|
+
begin
|
337
|
+
out = ""
|
338
|
+
for i in 0..(fk.all_foreign_key_field.size - 1)
|
339
|
+
fkf = fk.all_foreign_key_field[i]
|
340
|
+
ixf = fk.all_index_field[i]
|
341
|
+
out += indent(depth, " <CWM:StructuralFeature xmi.idref=\"#{fkf.component.xmiid}\" uniqueKey=\"#{ixf.component.index_xmiid}\" />")
|
342
|
+
end
|
343
|
+
out
|
344
|
+
end +
|
314
345
|
indent(depth, " </CWM:KeyRelationship.feature>") +
|
315
346
|
indent(depth, "</CWMRDB:ForeignKey>")
|
316
347
|
end
|
@@ -322,154 +353,6 @@ module ActiveFacts
|
|
322
353
|
|
323
354
|
end
|
324
355
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
########################
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
#
|
334
|
-
# Dump functions
|
335
|
-
#
|
336
|
-
# def entity_type_dump(o, level)
|
337
|
-
# pi = o.preferred_identifier
|
338
|
-
# supers = o.supertypes
|
339
|
-
# if (supers.size > 0) # Ignore identification by a supertype:
|
340
|
-
# pi = nil if pi && pi.role_sequence.all_role_ref.detect{ |rr|
|
341
|
-
# rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
342
|
-
# }
|
343
|
-
# end
|
344
|
-
#
|
345
|
-
# cn_array = o.concept.all_context_note_as_relevant_concept.map{|cn| [cn.context_note_kind, cn.discussion] }
|
346
|
-
# cn_hash = cn_array.inject({}) do |hash, value|
|
347
|
-
# hash[value.first] = value.last
|
348
|
-
# hash
|
349
|
-
# end
|
350
|
-
#
|
351
|
-
# informal_defn = cn_hash["because"]
|
352
|
-
# defn_term =
|
353
|
-
# " <div class=\"row\">\n" +
|
354
|
-
# " <div class=\"col-md-12 definition\">\n" +
|
355
|
-
# " A #{termdef(o.name)} #{informal_defn ? 'is ' + informal_defn : ''}\n" +
|
356
|
-
# " </div>\n" +
|
357
|
-
# " </div>\n"
|
358
|
-
#
|
359
|
-
# defn_detail =
|
360
|
-
# " <div class=\"row\">\n" +
|
361
|
-
# " <div class=\"col-md-12 details\">\n" +
|
362
|
-
# (supers.size > 0 ?
|
363
|
-
# "#{span('Each', 'keyword')} #{termref(o.name, nil, o)} #{span('is a kind of', 'keyword')} #{supers.map{|s| termref(s.name, nil, s)}*', '}\n" :
|
364
|
-
# ''
|
365
|
-
# ) +
|
366
|
-
# if pi
|
367
|
-
# "#{span('Each', 'keyword')} #{termref(o.name, nil, o)} #{span('is identified by', 'keyword')} " +
|
368
|
-
# pi.role_sequence.all_role_ref_in_order.map do |rr|
|
369
|
-
# termref(
|
370
|
-
# rr.role.object_type.name,
|
371
|
-
# [ rr.leading_adjective,
|
372
|
-
# rr.role.role_name || rr.role.object_type.name,
|
373
|
-
# rr.trailing_adjective
|
374
|
-
# ].compact * '-',
|
375
|
-
# rr.role.object_type
|
376
|
-
# )
|
377
|
-
# end * ", " + "\n"
|
378
|
-
# else
|
379
|
-
# ''
|
380
|
-
# end +
|
381
|
-
# fact_types_dump(o, relevant_fact_types(o)) + "\n" +
|
382
|
-
# " </div>\n" +
|
383
|
-
# " </div>\n"
|
384
|
-
#
|
385
|
-
# defn_term + defn_detail
|
386
|
-
# end
|
387
|
-
#
|
388
|
-
# def relevant_fact_types(o)
|
389
|
-
# o.
|
390
|
-
# all_role.
|
391
|
-
# map{|r| [r, r.fact_type]}.
|
392
|
-
# reject { |r, ft| ft.is_a?(ActiveFacts::Metamodel::LinkFactType) }.
|
393
|
-
# select { |r, ft| ft.entity_type || has_another_nonstatic_role(ft, r) }
|
394
|
-
# end
|
395
|
-
#
|
396
|
-
# def has_another_nonstatic_role(ft, r)
|
397
|
-
# ft.all_role.detect do |rr|
|
398
|
-
# rr != r &&
|
399
|
-
# rr.object_type.is_a?(ActiveFacts::Metamodel::EntityType) &&
|
400
|
-
# !rr.object_type.is_static
|
401
|
-
# end
|
402
|
-
# end
|
403
|
-
#
|
404
|
-
# def fact_types_dump(o, ftm)
|
405
|
-
# ftm.
|
406
|
-
# map { |r, ft| [ft, " #{fact_type_dump(ft, o)}"] }.
|
407
|
-
# sort_by{|ft, text| [ ft.is_a?(ActiveFacts::Metamodel::TypeInheritance) ? 0 : 1, text]}.
|
408
|
-
# map{|ft, text| text} * "\n"
|
409
|
-
# end
|
410
|
-
#
|
411
|
-
# def fact_type_dump(ft, wrt = nil)
|
412
|
-
# if ft.entity_type
|
413
|
-
# div(
|
414
|
-
# div(span('Each ', 'keyword') + termref(ft.entity_type.name, nil, ft.entity_type) + span(' is where ', 'keyword')) +
|
415
|
-
# div(expand_fact_type(ft, wrt, true, 'some')),
|
416
|
-
# 'glossary-objectification'
|
417
|
-
# )
|
418
|
-
# else
|
419
|
-
# fact_type_block(ft, wrt)
|
420
|
-
# end
|
421
|
-
# end
|
422
|
-
#
|
423
|
-
# def fact_type_block(ft, wrt = nil, include_rolenames = true)
|
424
|
-
# div(expand_fact_type(ft, wrt, include_rolenames, ''), 'glossary-facttype')
|
425
|
-
# end
|
426
|
-
#
|
427
|
-
# def expand_fact_type(ft, wrt = nil, include_rolenames = true, wrt_qualifier = '')
|
428
|
-
# role = ft.all_role.detect{|r| r.object_type == wrt}
|
429
|
-
# preferred_reading = ft.reading_preferably_starting_with_role(role)
|
430
|
-
# alternate_readings = ft.all_reading.reject{|r| r == preferred_reading}
|
431
|
-
#
|
432
|
-
# div(
|
433
|
-
# expand_reading(preferred_reading, include_rolenames, wrt, wrt_qualifier),
|
434
|
-
# 'glossary-reading'
|
435
|
-
# )
|
436
|
-
# end
|
437
|
-
#
|
438
|
-
# def role_ref(rr, freq_con, l_adj, name, t_adj, role_name_def, literal)
|
439
|
-
# term_parts = [l_adj, termref(name, nil, rr.role.object_type), t_adj].compact
|
440
|
-
# [
|
441
|
-
# freq_con ? element(freq_con, :class=>:keyword) : nil,
|
442
|
-
# term_parts.size > 1 ? term([l_adj, termref(name, nil, rr.role.object_type), t_adj].compact*' ') : term_parts[0],
|
443
|
-
# role_name_def,
|
444
|
-
# literal
|
445
|
-
# ]
|
446
|
-
# end
|
447
|
-
#
|
448
|
-
# def expand_reading(reading, include_rolenames = true, wrt = nil, wrt_qualifier = '')
|
449
|
-
# role_refs = reading.role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
|
450
|
-
# lrr = role_refs[role_refs.size - 1]
|
451
|
-
# element(
|
452
|
-
# # element(rr.role.is_unique ? "one" : "some", :class=>:keyword) +
|
453
|
-
# reading.expand([], include_rolenames) do |rr, freq_con, l_adj, name, t_adj, role_name_def, literal|
|
454
|
-
# if role_name_def
|
455
|
-
# role_name_def = role_name_def.gsub(/\(as ([^)]+)\)/) {
|
456
|
-
# span("(as #{ termref(rr.role.object_type.name, $1, rr.role.object_type) })", 'keyword')
|
457
|
-
# }
|
458
|
-
# end
|
459
|
-
# # qualify the last role of the reading
|
460
|
-
# quantifier = ''
|
461
|
-
# if rr == lrr
|
462
|
-
# uniq = true
|
463
|
-
# (0 ... role_refs.size - 2).each{|i| uniq = uniq && role_refs[i].role.is_unique }
|
464
|
-
# quantifier = uniq ? "one" : "at least one"
|
465
|
-
# end
|
466
|
-
# role_ref(rr, quantifier, l_adj, name, t_adj, role_name_def, literal)
|
467
|
-
# end,
|
468
|
-
# {:class => 'reading'}
|
469
|
-
# )
|
470
|
-
# end
|
471
|
-
|
472
|
-
|
473
356
|
def boolean_type
|
474
357
|
'boolean'
|
475
358
|
end
|
@@ -478,107 +361,6 @@ module ActiveFacts
|
|
478
361
|
'bigint'
|
479
362
|
end
|
480
363
|
|
481
|
-
# def component_type component, column_name
|
482
|
-
# case component
|
483
|
-
# when MM::Indicator
|
484
|
-
# boolean_type
|
485
|
-
# when MM::SurrogateKey
|
486
|
-
# surrogate_type
|
487
|
-
# when MM::ValueField, MM::Absorption
|
488
|
-
# object_type = component.object_type
|
489
|
-
# while object_type.is_a?(MM::EntityType)
|
490
|
-
# rr = object_type.preferred_identifier.role_sequence.all_role_ref.single
|
491
|
-
# raise "Can't produce a column for composite #{component.inspect}" unless rr
|
492
|
-
# object_type = rr.role.object_type
|
493
|
-
# end
|
494
|
-
# raise "A column can only be produced from a ValueType" unless object_type.is_a?(MM::ValueType)
|
495
|
-
#
|
496
|
-
# if component.is_a?(MM::Absorption)
|
497
|
-
# value_constraint ||= component.child_role.role_value_constraint
|
498
|
-
# end
|
499
|
-
#
|
500
|
-
# supertype = object_type
|
501
|
-
# begin
|
502
|
-
# object_type = supertype
|
503
|
-
# length ||= object_type.length
|
504
|
-
# scale ||= object_type.scale
|
505
|
-
# unless component.parent.parent and component.parent.foreign_key
|
506
|
-
# # No need to enforce value constraints that are already enforced by a foreign key
|
507
|
-
# value_constraint ||= object_type.value_constraint
|
508
|
-
# end
|
509
|
-
# end while supertype = object_type.supertype
|
510
|
-
# type, length = normalise_type(object_type.name, length)
|
511
|
-
# sql_type = "#{type}#{
|
512
|
-
# if !length
|
513
|
-
# ''
|
514
|
-
# else
|
515
|
-
# '(' + length.to_s + (scale ? ", #{scale}" : '') + ')'
|
516
|
-
# end
|
517
|
-
# # }#{
|
518
|
-
# # (component.path_mandatory ? '' : ' NOT') + ' NULL'
|
519
|
-
# # }#{
|
520
|
-
# # # REVISIT: This is an SQL Server-ism. Replace with a standard SQL SEQUENCE/
|
521
|
-
# # # Emit IDENTITY for columns auto-assigned on commit (except FKs)
|
522
|
-
# # if a = object_type.is_auto_assigned and a != 'assert' and
|
523
|
-
# # !component.all_foreign_key_field.detect{|fkf| fkf.foreign_key.source_composite == component.root}
|
524
|
-
# # ' IDENTITY'
|
525
|
-
# # else
|
526
|
-
# # ''
|
527
|
-
# # end
|
528
|
-
# }#{
|
529
|
-
# value_constraint ? check_clause(column_name, value_constraint) : ''
|
530
|
-
# }"
|
531
|
-
# when MM::Injection
|
532
|
-
# component.object_type.name
|
533
|
-
# else
|
534
|
-
# raise "Can't make a column from #{component}"
|
535
|
-
# end
|
536
|
-
# end
|
537
|
-
|
538
|
-
# def generate_index index, delayed_indices, indent
|
539
|
-
# nullable_columns =
|
540
|
-
# index.all_index_field.select do |ixf|
|
541
|
-
# !ixf.component.path_mandatory
|
542
|
-
# end
|
543
|
-
# contains_nullable_columns = nullable_columns.size > 0
|
544
|
-
#
|
545
|
-
# primary = index.composite_as_primary_index && !contains_nullable_columns
|
546
|
-
# column_names =
|
547
|
-
# index.all_index_field.map do |ixf|
|
548
|
-
# column_name(ixf.component)
|
549
|
-
# end
|
550
|
-
# clustering =
|
551
|
-
# (index.composite_as_primary_index ? ' CLUSTERED' : ' NONCLUSTERED')
|
552
|
-
#
|
553
|
-
# if contains_nullable_columns
|
554
|
-
# table_name = safe_table_name(index.composite)
|
555
|
-
# delayed_indices <<
|
556
|
-
# 'CREATE UNIQUE'+clustering+' INDEX '+
|
557
|
-
# escape("#{table_name(index.composite)}By#{column_names*''}", index_name_max) +
|
558
|
-
# " ON #{table_name}("+column_names.map{|n| escape(n, column_name_max)}*', ' +
|
559
|
-
# ") WHERE #{
|
560
|
-
# nullable_columns.
|
561
|
-
# map{|ixf| safe_column_name ixf.component}.
|
562
|
-
# map{|column_name| column_name + ' IS NOT NULL'} *
|
563
|
-
# ' AND '
|
564
|
-
# }"
|
565
|
-
# nil
|
566
|
-
# else
|
567
|
-
# # '-- '+index.inspect
|
568
|
-
# " " * indent + (primary ? 'PRIMARY KEY' : 'UNIQUE') +
|
569
|
-
# clustering +
|
570
|
-
# "(#{column_names.map{|n| escape(n, column_name_max)}*', '})"
|
571
|
-
# end
|
572
|
-
# end
|
573
|
-
|
574
|
-
# def generate_foreign_key fk, indent
|
575
|
-
# # '-- '+fk.inspect
|
576
|
-
# " " * indent + "FOREIGN KEY (" +
|
577
|
-
# fk.all_foreign_key_field.map{|fkf| safe_column_name fkf.component}*", " +
|
578
|
-
# ") REFERENCES <a href=\"#LDMD_#{table_name fk.composite}\">#{table_name fk.composite}</a> (" +
|
579
|
-
# fk.all_index_field.map{|ixf| safe_column_name ixf.component}*", " +
|
580
|
-
# ")"
|
581
|
-
# end
|
582
364
|
|
583
365
|
def reserved_words
|
584
366
|
@reserved_words ||= %w{ }
|
@@ -593,10 +375,6 @@ module ActiveFacts
|
|
593
375
|
@reserved_word_hash[w.upcase]
|
594
376
|
end
|
595
377
|
|
596
|
-
# def go s = ''
|
597
|
-
# "#{s}\nGO\n" # REVISIT: This is an SQL-Serverism. Move it to a subclass.
|
598
|
-
# end
|
599
|
-
|
600
378
|
def escape s, max = table_name_max
|
601
379
|
# Escape SQL keywords and non-identifiers
|
602
380
|
if s.size > max
|