annotate Lib/IMPL/ORM/Schema/TransformToSQL.pm @ 47:a9b70d836b28

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