Mercurial > pub > Impl
comparison lib/IMPL/ORM/Schema/TransformToSQL.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
406:f23fcb19d3c1 | 407:c6e90e02dd17 |
---|---|
1 package IMPL::ORM::Schema::TransformToSQL; | |
2 use strict; | |
3 use warnings; | |
4 | |
5 use parent qw(IMPL::DOM::Transform); | |
6 use IMPL::Class::Property; | |
7 use IMPL::SQL::Types qw(DateTime Varchar Integer Float Text Binary); | |
8 | |
9 require IMPL::SQL::Schema; | |
10 | |
11 BEGIN { | |
12 public property Types => prop_get | owner_set; | |
13 } | |
14 | |
15 our %CTOR = ( | |
16 'IMPL::DOM::Transform' => sub { | |
17 ORMSchema => \&ORMSchemaTransform, | |
18 Entity => \&EntityTransform, | |
19 Field => \&FieldTransform, | |
20 HasOne => \&HasOneTransform, | |
21 HasMany => \&HasManyTransform, | |
22 Subclass => \&SubclassTransform, | |
23 ValueType => sub {} | |
24 } | |
25 ); | |
26 | |
27 sub CTOR { | |
28 my ($this,$refTypeMap) = @_; | |
29 | |
30 $this->Types($refTypeMap) or die new IMPL::InvalidArgumentException("A reference to the type map hash is required"); | |
31 } | |
32 | |
33 sub ORMSchemaTransform { | |
34 my ($this,$node) = @_; | |
35 | |
36 my $schema = IMPL::SQL::Schema->new(Name => ref $node); | |
37 | |
38 my @constraints; | |
39 | |
40 my %ctx = (Schema => $schema); | |
41 | |
42 # all tables | |
43 foreach my $entity ($node->selectNodes('Entity')) { | |
44 $schema->AddTable($this->Transform($entity,\%ctx)); | |
45 push @constraints, $entity->selectNodes(sub {$_->isa('IMPL::ORM::Schema::Relation')}); | |
46 } | |
47 | |
48 # establish relations | |
49 $this->Transform($_,\%ctx) foreach @constraints; | |
50 | |
51 return $schema; | |
52 } | |
53 | |
54 sub EntityTransform { | |
55 my ($this,$node,$ctx) = @_; | |
56 | |
57 my $table = IMPL::SQL::Schema::Table->new(Name => $node->entityName, Schema => $ctx->{Schema}); | |
58 | |
59 $this->MakePrimaryKey($table); | |
60 | |
61 $table->InsertColumn( $this->Transform($_,$ctx)) foreach$node->selectNodes('Field'); | |
62 | |
63 return $table; | |
64 } | |
65 | |
66 sub FieldTransform { | |
67 my ($this,$field,$ctx) = @_; | |
68 | |
69 return { | |
70 Name => $field->fieldName, | |
71 Type => $this->MapType($field->fieldType) || die new IMPL::Exception("Can't get map a rom schema type to the SQL type",$field->fieldType), | |
72 CanBeNull => $field->fieldNullable | |
73 }; | |
74 } | |
75 | |
76 sub HasOneTransform { | |
77 my ($this,$relation,$ctx) = @_; | |
78 | |
79 my $sqlSchema = $ctx->{Schema}; | |
80 my $table = $sqlSchema->Tables->{$relation->parentNode->entityName}; | |
81 my $tableForeign = $sqlSchema->Tables->{$relation->target}; | |
82 my $prefix = $relation->name; | |
83 | |
84 my @fkColumns = $tableForeign->PrimaryKey->columns; | |
85 | |
86 if (@fkColumns > 1) { | |
87 @fkColumns = map | |
88 $table->InsertColumn({ | |
89 Name => $prefix . $_->Name, | |
90 Type => $_->Type, | |
91 CanBeNull => 1 | |
92 }), @fkColumns; | |
93 } else { | |
94 @fkColumns = $table->InsertColumn({ | |
95 Name => $prefix, | |
96 Type => $fkColumns[0]->Type, | |
97 CanBeNull => 1 | |
98 }); | |
99 } | |
100 | |
101 $table->LinkTo($tableForeign,@fkColumns); | |
102 } | |
103 | |
104 sub HasManyTransform { | |
105 my ($this,$relation,$ctx) = @_; | |
106 | |
107 #similar to HasOne | |
108 | |
109 my $sqlSchema = $ctx->{Schema}; | |
110 my $table = $sqlSchema->Tables->{$relation->parentNode->entityName}; | |
111 my $tableForeign = $sqlSchema->Tables->{$relation->target}; | |
112 my $prefix = $relation->name; | |
113 | |
114 my @fkColumns = $table->PrimaryKey->columns; | |
115 | |
116 if (@fkColumns > 1 ) { | |
117 @fkColumns = map $tableForeign->InsertColumn({ | |
118 Name => $prefix . $_->Name, | |
119 Type => $_->Type, | |
120 CanBeNull => 1 | |
121 }), @fkColumns; | |
122 } else { | |
123 @fkColumns = $tableForeign->InsertColumn({ | |
124 Name => $prefix, | |
125 Type => $fkColumns[0]->Type, | |
126 CanBeNull => 1 | |
127 }); | |
128 } | |
129 | |
130 $tableForeign->LinkTo($table,@fkColumns); | |
131 } | |
132 | |
133 sub SubclassTransform { | |
134 # actually this rlations has only logical implementation | |
135 } | |
136 | |
137 sub MapType { | |
138 my ($this,$typeName) = @_; | |
139 | |
140 $this->Types->{$typeName} || die new IMPL::Exception("Can't map a type",$typeName); | |
141 } | |
142 | |
143 sub MakePrimaryKey { | |
144 my ($this,$table) = @_; | |
145 | |
146 $table->InsertColumn( {Name => '_Id', Type => Integer } ); | |
147 $table->SetPrimaryKey('_Id'); | |
148 } | |
149 | |
150 { | |
151 my $std; | |
152 sub Std { | |
153 $std ||= __PACKAGE__->new({ | |
154 String => Varchar(255), | |
155 DateTime => DateTime, | |
156 Integer => Integer, | |
157 Float => Float(24), | |
158 Decimal => Float(53), | |
159 Real => Float(24), | |
160 Binary => Binary, | |
161 Text => Text | |
162 }); | |
163 } | |
164 } | |
165 | |
166 1; | |
167 | |
168 __END__ | |
169 | |
170 =pod | |
171 | |
172 =head1 SYNOPSIS | |
173 | |
174 =begin code | |
175 | |
176 my $sqlSchema = IMPL::ORM::Schema::TransformToSQL->Default->Transform(Data::Schema->instance); | |
177 | |
178 =end code | |
179 | |
180 =cut | |
181 |