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