Mercurial > pub > Impl
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 |
