comparison Lib/IMPL/ORM/Schema/TransformToSQL.pm @ 38:d660fb38b7cc

small fixes ORM shema to SQL schema transformation
author Sergey
date Mon, 23 Nov 2009 17:57:07 +0300
parents
children 32d2350fccf9
comparison
equal deleted inserted replaced
37:c2e7f7c96bcd 38:d660fb38b7cc
1 package IMPL::ORM::Schema::TransformToSQL;
2 use strict;
3 use warnings;
4
5 use base 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 }
24 );
25
26 sub CTOR {
27 my ($this,$refTypeMap) = @_;
28
29 $this->Types($refTypeMap) or die new IMPL::InvalidArgumentException("A reference to the type map hash is required");
30 }
31
32 sub ORMSchemaTransform {
33 my ($this,$node) = @_;
34
35 my $schema = IMPL::SQL::Schema->new(Name => ref $node);
36
37 my @constraints;
38
39 my %ctx = (Schema => $schema);
40
41 # all tables
42 foreach my $entity ($node->ReferenceTypes) {
43 $schema->AddTable($this->Transform($entity,\%ctx));
44 push @constraints, $entity->selectNodes(sub {$_->isa('IMPL::ORM::Schema::Relation')});
45 }
46
47 # establish relations
48 $this->Transform($_,\%ctx) foreach @constraints;
49
50 return $schema;
51 }
52
53 sub EntityTransform {
54 my ($this,$node,$ctx) = @_;
55
56 my $table = IMPL::SQL::Schema::Table->new(Name => $node->entityName, Schema => $ctx->{Schema});
57
58 $this->MakePrimaryKey($table);
59
60 $table->InsertColumn( $this->Transform($_,$ctx)) foreach$node->selectNodes('Field');
61
62 return $table;
63 }
64
65 sub FieldTransform {
66 my ($this,$field,$ctx) = @_;
67
68 return {
69 Name => $field->fieldName,
70 Type => $this->MapType($field->fieldType) || die new IMPL::Exception("Can't get map a rom schema type to the SQL type",$field->fieldType),
71 CanBeNull => $field->fieldNullable
72 };
73 }
74
75 sub HasOneTransform {
76 my ($this,$relation,$ctx) = @_;
77
78 my $sqlSchema = $ctx->{Schema};
79 my $table = $sqlSchema->Tables->{$relation->parentNode->entityName};
80 my $tableForeign = $sqlSchema->Tables->{$relation->target};
81 my $prefix = $relation->name;
82
83 my @fkColumns = map
84 $table->InsertColumn({
85 Name => $prefix . $_->Name,
86 Type => $_->Type,
87 CanBeNull => 1
88 }),
89 @{$tableForeign->PrimaryKey->Columns};
90
91 $table->LinkTo($tableForeign,@fkColumns);
92 }
93
94 sub HasManyTransform {
95 my ($this,$relation,$ctx) = @_;
96
97 #similar to HasOne
98
99 my $sqlSchema = $ctx->{Schema};
100 my $table = $sqlSchema->Tables->{$relation->parentNode->entityName};
101 my $tableForeign = $sqlSchema->Tables->{$relation->target};
102 my $prefix = $table->Name . '_' . $relation->name;
103
104 my @fkColumns = map
105 $tableForeign->InsertColumn({
106 Name => $prefix . $_->Name,
107 Type => $_->Type,
108 CanBeNull => 1
109 }),
110 @{$table->PrimaryKey->Columns};
111
112 $tableForeign->LinkTo($table,@fkColumns);
113 }
114
115 sub SubclassTransform {
116 # actually this rlations has only ligical implementation
117 }
118
119 sub MapType {
120 my ($this,$typeName) = @_;
121
122 $this->Types->{$typeName} || die new IMPL::Exception("Can't map a type",$typeName);
123 }
124
125 sub MakePrimaryKey {
126 my ($this,$table) = @_;
127
128 $table->InsertColumn( {Name => '_Id', Type => Integer } );
129 $table->SetPrimaryKey('_Id');
130 }
131
132 {
133 my $std;
134 sub Std {
135 $std ||= __PACKAGE__->new({
136 String => Varchar(255),
137 DateTime => DateTime,
138 Integer => Integer,
139 Float => Float(24),
140 Decimal => Float(53),
141 Real => Float(24),
142 Binary => Binary,
143 Text => Text
144 });
145 }
146 }
147
148 1;
149
150 __END__
151
152 =pod
153
154 =head1 SYNOPSIS
155
156 my $sqlSchema = IMPL::ORM::Schema::TransformToSQL->Default->Transform(Data::Schema->instance);
157
158 =cut
159