MT::Meta::Proxy - MySQL bulk inserts
sub save { | |
my $proxy = shift; | |
# perl funkiness ... keys %{ $proxy->{__objects} } will automatically clobber | |
# empty hash reference on that key! | |
return unless $proxy->{__objects}; | |
my @cols = qw( type vchar vchar_idx vdatetime | |
vdatetime_idx vinteger vinteger_idx vfloat | |
vfloat_idx vblob vclob ); | |
my $od = lc( MT->config( 'ObjectDriver' ) ); | |
my $bulk_insert = MT->config( 'BulkInsertMeta' ); | |
unless ( $od =~ /mysql/ && $bulk_insert ) { | |
$bulk_insert = undef; | |
} | |
if ( MT->request( 'meta-save-retry' ) ) { | |
# retry | |
$bulk_insert = undef; | |
} | |
my $ds; | |
my $i = 0; | |
my @col_names; | |
my @col_values; | |
my @update_cols; | |
my $obj_id; | |
my $dbd; | |
my $replace; | |
my $count_field; | |
my $driver = MT::Object->driver; | |
my $dbh = $driver->{ fallback }->{ dbh }; | |
foreach my $field ( keys %{ $proxy->{__objects} } ) { | |
next if $field eq ''; | |
next unless $proxy->is_changed($field); | |
my $meta_obj = $proxy->{__objects}->{$field}; | |
## primary key from core object | |
foreach my $pkey ( keys %{ $proxy->{__pkeys} } ) { | |
next if ( $pkey eq 'type' ); | |
my $pval = $proxy->{__pkeys}->{$pkey}; | |
$meta_obj->$pkey($pval); | |
} | |
my $pkg = $proxy->{pkg}; | |
my $meta = $proxy->META_CLASS()->metadata_by_name( $pkg, $field ) | |
or next; # XXX: Carp::croak("Metadata $field on $pkg not found."); | |
my $type = $meta->{type}; | |
my $meta_col_def = $meta_obj->column_def($type); | |
my $meta_is_blob | |
= $meta_col_def ? $meta_col_def->{type} eq 'blob' : 0; | |
my $enc = MT->config->PublishCharset || 'UTF-8'; | |
my ( $data, $utf8_data ); | |
$data = $utf8_data = $meta_obj->$type; | |
$dbd = $meta_obj->driver->dbd; | |
unless ( ref $data ) { | |
$data = Encode::encode( $enc, $data ) | |
if Encode::is_utf8($data) && $dbd->need_encode; | |
} | |
if (!$ds) { | |
$ds = $meta->{pkg}; | |
$ds = $ds->datasource; | |
} | |
my $column_values = $meta_obj->column_values; | |
my @_col_values; | |
if ( $bulk_insert ) { | |
for my $col( @cols ) { | |
my $col_name = $ds . '_meta_' . $col; | |
if (! $i ) { | |
push @col_names, $col_name; | |
push @update_cols, "${col_name}=VALUES(${col_name})"; | |
} | |
my ( $data, $utf8_data ); | |
$data = $column_values->{ $col }; | |
if ( $col eq 'vblob' ) { | |
if ( ref $data ) { | |
$data = 'BIN:' . $serializer->serialize( \$data ); | |
} elsif ( defined $data ) { | |
$data = 'ASC:' . $data; | |
} else { | |
$data = undef; | |
} | |
} | |
$data = $dbh->quote( $data ); | |
push @_col_values, $data; | |
} | |
$obj_id = $column_values->{ $ds . '_id' }; | |
if (! $i ) { | |
push @col_names, $ds . '_meta_' . $ds . '_id'; | |
$count_field = $meta_obj->count({ $ds . '_id' => $obj_id }); | |
} | |
push @_col_values, $obj_id; | |
my $c_values = ''; | |
for my $v ( @_col_values ) { | |
if ( $c_values ) { | |
$c_values .= ','; | |
} | |
if ( defined $v ) { | |
$c_values .= $v; | |
} else { | |
$c_values .= 'NULL'; | |
} | |
} | |
$c_values = "(${c_values})"; | |
push @col_values, $c_values; | |
# push @col_values, '(' . join(',',@_col_values) . ')'; | |
} | |
$i++; | |
$meta_obj->$type( $data, { no_changed_flag => 1 } ); | |
## xxx can be a hook? | |
if ( !defined $meta_obj->$type() ) { | |
$meta_obj->remove; | |
} | |
else { | |
serialize_blob( $field, $meta_obj ) if $meta_is_blob; | |
my $meta_class = $proxy->META_CLASS(); | |
if (! $bulk_insert ) { | |
{ | |
no strict 'refs'; | |
if ( ${"${meta_class}::REPLACE_ENABLED"} ) { | |
$meta_obj->replace; | |
} | |
else { | |
$meta_obj->save; | |
} | |
} | |
} | |
unserialize_blob($meta_obj) if $meta_is_blob; | |
} | |
unless ( ref $utf8_data ) { | |
$meta_obj->$type( $utf8_data, { no_changed_flag => 1 } ); | |
} | |
} | |
if ( $bulk_insert ) { | |
if ( @col_values ) { | |
my ( $driver, $dbh, $sth, $do ); | |
$driver = MT::Object->driver; | |
my $query = 'INSERT INTO mt_' . $ds . '_meta (' . join(',',@col_names) . ') values '; | |
$query .= join(',',@col_values); | |
if ( $count_field ) { | |
$query .= 'ON DUPLICATE KEY UPDATE ' . join(',',@update_cols); | |
} | |
$dbh = $driver->{ fallback }->{ dbh }; | |
$sth = $dbh->prepare( $query ); | |
if ( $dbh->errstr ) { | |
MT->log( MT->translate( "Error in query: " . $dbh->errstr ) ); | |
MT->request( 'meta-save-retry', 1 ); | |
save( @_ ); | |
} | |
$do = $sth->execute(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment