root/branches/release-26/lib/MT/ObjectDriver/DDL/mysql.pm @ 1174

Revision 1174, 6.1 kB (checked in by bchoate, 23 months ago)

Updated copyright year for source.

  • Property svn:keywords set to Id Revision
Line 
1# Movable Type (r) Open Source (C) 2001-2008 Six Apart, Ltd.
2# This program is distributed under the terms of the
3# GNU General Public License, version 2.
4#
5# $Id$
6
7package MT::ObjectDriver::DDL::mysql;
8
9use strict;
10use warnings;
11use base qw( MT::ObjectDriver::DDL );
12
13sub can_add_column { 1 }
14sub can_drop_column { 1 }
15sub can_alter_column { 1 }
16
17sub index_defs {
18    my $ddl = shift;
19    my ($class) = @_;
20    my $driver = $class->driver;
21    my $dbh = $driver->r_handle;
22    my $field_prefix = $class->datasource;
23    my $table_name = $class->table_name;
24    my $sth = $dbh->prepare('SHOW INDEX FROM ' . $table_name)
25        or return undef;
26    $sth->execute or return undef;
27
28    my $bags = {};
29    my $unique = {};
30    while (my $row = $sth->fetchrow_hashref) {
31        my $key = $row->{'Key_name'};
32        next unless $key =~ m/^(mt_)?\Q$field_prefix\E_/;
33        $key = 'mt_' . $key unless $key =~ m/^mt_/;
34
35        my $type = $row->{'Index_type'};
36
37        # ignore fulltext or other unrecognized indexes for now
38        next unless $type eq 'BTREE';
39
40        my $seq = $row->{'Seq_in_index'};
41        my $col = $row->{'Column_name'};
42        my $non_unique = $row->{'Non_unique'};
43        my $null = $row->{'Null'};
44        $key =~ s/^mt_\Q$field_prefix\E_//;
45        $col =~ s/^\Q$field_prefix\E_//;
46        $unique->{$key} = 1 unless $non_unique;
47        my $idx_bag = $bags->{$key} ||= [];
48        $idx_bag->[$seq - 1] = $col;
49    }
50    $sth->finish;
51    if (!%$bags) {
52        return undef;
53    }
54
55    my $defs = {};
56    foreach my $key (keys %$bags) {
57        my $cols = $bags->{$key};
58        if ($unique->{$key}) {
59            $defs->{$key} = { columns => $cols, unique => 1 };
60        }
61        else {
62            if ((@$cols == 1) && ($key eq $cols->[0])) {
63                $defs->{$key} = 1;
64            } else {
65                $defs->{$key} = { columns => $cols };
66            }
67        }
68    }
69
70    return $defs;
71}
72
73sub column_defs {
74    my $ddl = shift; 
75    my ($class) = @_;
76
77    my $driver = $class->driver;
78    my $dbh = $driver->r_handle;
79    my $field_prefix = $class->datasource;
80    my $table_name = $class->table_name;
81
82    # Disable RaiseError if set, since the table we're about to describe
83    # may not actually exist (in which case, the return value is undef,
84    # signalling an nonexistent table to the caller).
85    local $dbh->{RaiseError} = 0;
86    my $sth = $dbh->prepare('describe ' . $table_name) or return undef;
87    $sth->execute or return undef;
88    my $defs = {};
89    while (my $row = $sth->fetchrow_hashref) {
90        my $colname = lc $row->{Field};
91        next if $colname !~ m/^\Q$field_prefix\E_/i;
92        $colname =~ s/^\Q$field_prefix\E_//i;
93        my $coltype = $row->{Type};
94        my ($size) = ($coltype =~ m/(?:var)?char\((\d+)\)/i ? $1 : undef);
95        $coltype = $ddl->db2type($coltype);
96        $defs->{$colname}{type} = $coltype;
97        $defs->{$colname}{auto} = ($row->{Extra} =~ m/auto_increment/i) ? 1 : 0;
98        if (($coltype eq 'string') && $size) {
99            $defs->{$colname}{size} = $size;
100        }
101        if ( !$row->{Null} || $row->{Null} eq 'NO' || ($coltype eq 'timestamp') ) {
102            $defs->{$colname}{not_null} = 1;
103        } else {
104            $defs->{$colname}{not_null} = 0;
105        }
106    }
107    $sth->finish;
108    if (!%$defs) {
109        return undef;
110    }
111    return $defs;
112}
113
114sub db2type {
115    my $ddl = shift;
116    my ($type) = @_;
117    $type = lc $type;
118    $type =~ s/\(.+//;
119    if ($type eq 'int') {
120        return 'integer';
121    } elsif ($type eq 'smallint') {
122        return 'smallint';
123    } elsif ($type eq 'bigint') {
124        return 'bigint';
125    } elsif ($type eq 'mediumint') {
126        return 'integer';
127    } elsif ($type eq 'bigint') {
128        return 'integer';
129    } elsif ($type eq 'varchar') {
130        return 'string';
131    } elsif ($type eq 'varbinary') {
132        return 'string';
133    } elsif ($type eq 'char') {
134        return 'string';
135    } elsif ($type eq 'mediumtext') {
136        return 'text';
137    } elsif ($type eq 'blob') {
138        return 'blob';
139    } elsif ($type eq 'mediumblob') {
140        return 'blob';
141    } elsif ($type eq 'tinyint') {
142        return 'boolean';
143    } elsif ($type eq 'datetime') {
144        return 'datetime';
145    } elsif ($type eq 'timestamp') {
146        return 'timestamp';
147    } elsif ($type eq 'text') {
148        return 'text';
149    } elsif ($type eq 'float') {
150        return 'float';
151    }
152    Carp::croak("undefined type: " . $type);
153}
154
155sub type2db {
156    my $ddl = shift;
157    my ($def) = @_; 
158    return undef if !defined $def;
159    my $type = $def->{type};
160    if ($type eq 'string') {
161        return 'varchar(' . $def->{size} . ')';
162    } elsif ($type eq 'smallint' ) {
163        return 'smallint';
164    } elsif ($type eq 'bigint' ) {
165        return 'bigint';
166    } elsif ($type eq 'boolean') {
167        return 'tinyint';
168    } elsif ($type eq 'datetime') {
169        return 'datetime';
170    } elsif ($type eq 'timestamp') {
171        return 'timestamp';
172    } elsif ($type eq 'integer') {
173        return 'integer';
174    } elsif ($type eq 'blob') {
175        return 'mediumblob';
176    } elsif ($type eq 'text') {
177        return 'mediumtext';
178    } elsif ($type eq 'float') {
179        return 'float';
180    }
181    Carp::croak("undefined type: ". $type);
182}
183
184sub column_sql {
185    my $ddl = shift;
186    my ($class, $name) = @_;
187    my $sql = $ddl->SUPER::column_sql($class, $name);
188    my $def = $class->column_def($name);
189    $sql .= ' auto_increment' if $def->{auto};
190    return $sql;
191}
192
193sub cast_column_sql {
194    my $ddl = shift;
195    my ($class, $name, $from_def) = @_;
196
197    my $def = $class->column_def($name);
198    my $field_prefix = $class->datasource;
199    my %cast_type = (
200        'string' => 'char',
201        'smallint' => 'signed',
202        'bigint' => 'signed',
203        'integer' => 'signed',
204        'blob' => 'binary',
205        'text' => 'char',
206        'datetime' => 'datetime',
207        'timestamp' => 'timestamp',
208        'boolean' => 'signed',
209        'float' => 'signed',
210    );
211    return "CAST(${field_prefix}_$name AS " . $cast_type{$def->{type}} . ')';
212}
213
214sub drop_table_sql {
215    my $ddl = shift;
216    my ($class) = @_;
217    my $table_name = $class->table_name;
218    return "DROP TABLE IF EXISTS $table_name";
219}
220
2211;
Note: See TracBrowser for help on using the browser.