1 package DBIx::Class::Storage::DBI;
2 # -*- mode: cperl; cperl-indent-level: 2 -*-
4 use base 'DBIx::Class::Storage';
9 use SQL::Abstract::Limit;
10 use DBIx::Class::Storage::DBI::Cursor;
11 use DBIx::Class::Storage::Statistics;
13 use Carp::Clan qw/DBIx::Class/;
16 package DBIC::SQL::Abstract; # Would merge upstream, but nate doesn't reply :(
18 use base qw/SQL::Abstract::Limit/;
21 my ($self, $table, $fields, $where, $order, @rest) = @_;
22 $table = $self->_quote($table) unless ref($table);
23 @rest = (-1) unless defined $rest[0];
24 die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
25 # and anyway, SQL::Abstract::Limit will cause a barf if we don't first
26 local $self->{having_bind} = [];
27 my ($sql, @ret) = $self->SUPER::select(
28 $table, $self->_recurse_fields($fields), $where, $order, @rest
30 return wantarray ? ($sql, @ret, @{$self->{having_bind}}) : $sql;
36 $table = $self->_quote($table) unless ref($table);
37 $self->SUPER::insert($table, @_);
43 $table = $self->_quote($table) unless ref($table);
44 $self->SUPER::update($table, @_);
50 $table = $self->_quote($table) unless ref($table);
51 $self->SUPER::delete($table, @_);
57 return $_[1].$self->_order_by($_[2]);
59 return $self->SUPER::_emulate_limit(@_);
64 my ($self, $fields) = @_;
65 my $ref = ref $fields;
66 return $self->_quote($fields) unless $ref;
67 return $$fields if $ref eq 'SCALAR';
69 if ($ref eq 'ARRAY') {
70 return join(', ', map { $self->_recurse_fields($_) } @$fields);
71 } elsif ($ref eq 'HASH') {
72 foreach my $func (keys %$fields) {
73 return $self->_sqlcase($func)
74 .'( '.$self->_recurse_fields($fields->{$func}).' )';
83 if (ref $_[0] eq 'HASH') {
84 if (defined $_[0]->{group_by}) {
85 $ret = $self->_sqlcase(' group by ')
86 .$self->_recurse_fields($_[0]->{group_by});
88 if (defined $_[0]->{having}) {
90 ($frag, @extra) = $self->_recurse_where($_[0]->{having});
91 push(@{$self->{having_bind}}, @extra);
92 $ret .= $self->_sqlcase(' having ').$frag;
94 if (defined $_[0]->{order_by}) {
95 $ret .= $self->SUPER::_order_by($_[0]->{order_by});
97 } elsif(ref $_[0] eq 'SCALAR') {
98 $ret = $self->_sqlcase(' order by ').${ $_[0] };
100 $ret = $self->SUPER::_order_by(@_);
105 sub _order_directions {
106 my ($self, $order) = @_;
107 $order = $order->{order_by} if ref $order eq 'HASH';
108 return $self->SUPER::_order_directions($order);
112 my ($self, $from) = @_;
113 if (ref $from eq 'ARRAY') {
114 return $self->_recurse_from(@$from);
115 } elsif (ref $from eq 'HASH') {
116 return $self->_make_as($from);
118 return $from; # would love to quote here but _table ends up getting called
119 # twice during an ->select without a limit clause due to
120 # the way S::A::Limit->select works. should maybe consider
121 # bypassing this and doing S::A::select($self, ...) in
122 # our select method above. meantime, quoting shims have
123 # been added to select/insert/update/delete here
128 my ($self, $from, @join) = @_;
130 push(@sqlf, $self->_make_as($from));
131 foreach my $j (@join) {
134 # check whether a join type exists
135 my $join_clause = '';
136 my $to_jt = ref($to) eq 'ARRAY' ? $to->[0] : $to;
137 if (ref($to_jt) eq 'HASH' and exists($to_jt->{-join_type})) {
138 $join_clause = ' '.uc($to_jt->{-join_type}).' JOIN ';
140 $join_clause = ' JOIN ';
142 push(@sqlf, $join_clause);
144 if (ref $to eq 'ARRAY') {
145 push(@sqlf, '(', $self->_recurse_from(@$to), ')');
147 push(@sqlf, $self->_make_as($to));
149 push(@sqlf, ' ON ', $self->_join_condition($on));
151 return join('', @sqlf);
155 my ($self, $from) = @_;
156 return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ : $self->_quote($_)) }
157 reverse each %{$self->_skip_options($from)});
161 my ($self, $hash) = @_;
163 $clean_hash->{$_} = $hash->{$_}
164 for grep {!/^-/} keys %$hash;
168 sub _join_condition {
169 my ($self, $cond) = @_;
170 if (ref $cond eq 'HASH') {
173 my $x = '= '.$self->_quote($cond->{$_}); $j{$_} = \$x;
175 return $self->_recurse_where(\%j);
176 } elsif (ref $cond eq 'ARRAY') {
177 return join(' OR ', map { $self->_join_condition($_) } @$cond);
179 die "Can't handle this yet!";
184 my ($self, $label) = @_;
185 return '' unless defined $label;
186 return "*" if $label eq '*';
187 return $label unless $self->{quote_char};
188 if(ref $self->{quote_char} eq "ARRAY"){
189 return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1]
190 if !defined $self->{name_sep};
191 my $sep = $self->{name_sep};
192 return join($self->{name_sep},
193 map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] }
194 split(/\Q$sep\E/,$label));
196 return $self->SUPER::_quote($label);
202 $_[0] =~ s/SELECT (.*?) FROM/
203 'SELECT '.join(', ', map { $_.' AS col'.++$c } split(', ', $1)).' FROM'/e;
204 $self->SUPER::_RowNum(@_);
209 $self->{limit_dialect} = shift if @_;
210 return $self->{limit_dialect};
215 $self->{quote_char} = shift if @_;
216 return $self->{quote_char};
221 $self->{name_sep} = shift if @_;
222 return $self->{name_sep};
225 } # End of BEGIN block
227 use base qw/DBIx::Class/;
229 __PACKAGE__->load_components(qw/AccessorGroup/);
231 __PACKAGE__->mk_group_accessors('simple' =>
232 qw/_connect_info _dbh _sql_maker _conn_pid _conn_tid debug debugobj
233 cursor on_connect_do transaction_depth/);
237 DBIx::Class::Storage::DBI - DBI storage handler
243 This class represents the connection to the database
252 my $new = bless({}, ref $_[0] || $_[0]);
253 $new->cursor("DBIx::Class::Storage::DBI::Cursor");
254 $new->transaction_depth(0);
256 $new->debugobj(new DBIx::Class::Storage::Statistics());
260 my $debug_env = $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}
263 if (defined($debug_env) && ($debug_env =~ /=(.+)$/)) {
264 $fh = IO::File->new($1, 'w')
265 or $new->throw_exception("Cannot open trace file $1");
267 $fh = IO::File->new('>&STDERR');
270 $new->debug(1) if $debug_env;
274 =head2 throw_exception
276 Throws an exception - croaks.
280 sub throw_exception {
281 my ($self, $msg) = @_;
287 The arguments of C<connect_info> are always a single array reference.
289 This is normally accessed via L<DBIx::Class::Schema/connection>, which
290 encapsulates its argument list in an arrayref before calling
291 C<connect_info> here.
293 The arrayref can either contain the same set of arguments one would
294 normally pass to L<DBI/connect>, or a lone code reference which returns
295 a connected database handle.
297 In either case, there is an optional final element within the arrayref
298 which can hold a hashref of connection-specific Storage::DBI options.
299 These include C<on_connect_do>, and the sql_maker options
300 C<limit_dialect>, C<quote_char>, and C<name_sep>. Examples:
302 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
304 ->connect_info([ sub { DBI->connect(...) } ]);
312 { quote_char => q{`}, name_sep => q{@} },
318 sub { DBI->connect(...) },
319 { quote_char => q{`}, name_sep => q{@} },
325 $schema->storage->on_connect_do(['PRAGMA synchronous = OFF']);
327 Call this after C<< $schema->connect >> to have the sql statements
328 given executed on every db connect.
330 This option can also be set via L</connect_info>.
334 Causes SQL trace information to be emitted on the C<debugobj> object.
335 (or C<STDERR> if C<debugobj> has not specifically been set).
339 Set or retrieve the filehandle used for trace/debug output. This should be
340 an IO::Handle compatible ojbect (only the C<print> method is used. Initially
341 set to be STDERR - although see information on the
342 L<DBIC_TRACE> environment variable.
349 if ($self->debugobj->can('debugfh')) {
350 return $self->debugobj->debugfh(@_);
356 Sets or retrieves the object used for metric collection. Defaults to an instance
357 of L<DBIx::Class::Storage::Statistics> that is campatible with the original
358 method of using a coderef as a callback. See the aforementioned Statistics
359 class for more information.
363 Sets a callback to be executed each time a statement is run; takes a sub
364 reference. Callback is executed as $sub->($op, $info) where $op is
365 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
367 See L<debugobj> for a better way.
374 if ($self->debugobj->can('callback')) {
375 return $self->debugobj->callback(@_);
381 Disconnect the L<DBI> handle, performing a rollback first if the
382 database is not in C<AutoCommit> mode.
389 if( $self->connected ) {
390 $self->_dbh->rollback unless $self->_dbh->{AutoCommit};
391 $self->_dbh->disconnect;
398 Check if the L<DBI> handle is connected. Returns true if the handle
403 sub connected { my ($self) = @_;
405 if(my $dbh = $self->_dbh) {
406 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
407 $self->_sql_maker(undef);
408 return $self->_dbh(undef);
410 elsif($self->_conn_pid != $$) {
411 $self->_dbh->{InactiveDestroy} = 1;
412 $self->_sql_maker(undef);
413 return $self->_dbh(undef)
415 return ($dbh->FETCH('Active') && $dbh->ping);
421 =head2 ensure_connected
423 Check whether the database handle is connected - if not then make a
428 sub ensure_connected {
431 unless ($self->connected) {
432 $self->_populate_dbh;
438 Returns the dbh - a data base handle of class L<DBI>.
445 $self->ensure_connected;
449 sub _sql_maker_args {
452 return ( limit_dialect => $self->dbh );
457 Returns a C<sql_maker> object - normally an object of class
458 C<DBIC::SQL::Abstract>.
464 unless ($self->_sql_maker) {
465 $self->_sql_maker(new DBIC::SQL::Abstract( $self->_sql_maker_args ));
467 return $self->_sql_maker;
471 my ($self, $info_arg) = @_;
475 my $info = [ @$info_arg ]; # copy because we can alter it
476 my $last_info = $info->[-1];
477 if(ref $last_info eq 'HASH') {
479 if(my $on_connect_do = $last_info->{on_connect_do}) {
481 $self->on_connect_do($on_connect_do);
483 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
484 if(my $opt_val = $last_info->{$sql_maker_opt}) {
486 $sql_maker_opts{$sql_maker_opt} = $opt_val;
490 # remove our options hashref if it was there, to avoid confusing
491 # DBI in the case the user didn't use all 4 DBI options, as in:
492 # [ 'dbi:SQLite:foo.db', { quote_char => q{`} } ]
493 pop(@$info) if $used;
496 $self->_connect_info($info);
497 $self->sql_maker->$_($sql_maker_opts{$_}) for(keys %sql_maker_opts);
500 $self->_connect_info;
505 my @info = @{$self->_connect_info || []};
506 $self->_dbh($self->_connect(@info));
508 if(ref $self eq 'DBIx::Class::Storage::DBI') {
509 my $driver = $self->_dbh->{Driver}->{Name};
510 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
511 bless $self, "DBIx::Class::Storage::DBI::${driver}";
512 $self->_rebless() if $self->can('_rebless');
516 # if on-connect sql statements are given execute them
517 foreach my $sql_statement (@{$self->on_connect_do || []}) {
518 $self->debugobj->query_start($sql_statement) if $self->debug();
519 $self->_dbh->do($sql_statement);
520 $self->debugobj->query_end($sql_statement) if $self->debug();
523 $self->_conn_pid($$);
524 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
528 my ($self, @info) = @_;
530 $self->throw_exception("You failed to provide any connection info")
533 my ($old_connect_via, $dbh);
535 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
536 $old_connect_via = $DBI::connect_via;
537 $DBI::connect_via = 'connect';
541 $dbh = ref $info[0] eq 'CODE'
543 : DBI->connect(@info);
546 $DBI::connect_via = $old_connect_via if $old_connect_via;
549 $self->throw_exception("DBI Connection failed: " . ($@ || $DBI::errstr));
557 Calls begin_work on the current dbh.
559 See L<DBIx::Class::Schema> for the txn_do() method, which allows for
560 an entire code block to be executed transactionally.
566 if ($self->{transaction_depth}++ == 0) {
567 my $dbh = $self->dbh;
568 if ($dbh->{AutoCommit}) {
569 $self->debugobj->txn_begin()
578 Issues a commit against the current dbh.
584 my $dbh = $self->dbh;
585 if ($self->{transaction_depth} == 0) {
586 unless ($dbh->{AutoCommit}) {
587 $self->debugobj->txn_commit()
593 if (--$self->{transaction_depth} == 0) {
594 $self->debugobj->txn_commit()
603 Issues a rollback against the current dbh. A nested rollback will
604 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
605 which allows the rollback to propagate to the outermost transaction.
613 my $dbh = $self->dbh;
614 if ($self->{transaction_depth} == 0) {
615 unless ($dbh->{AutoCommit}) {
616 $self->debugobj->txn_rollback()
622 if (--$self->{transaction_depth} == 0) {
623 $self->debugobj->txn_rollback()
628 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
635 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
636 $error =~ /$exception_class/ and $self->throw_exception($error);
637 $self->{transaction_depth} = 0; # ensure that a failed rollback
638 $self->throw_exception($error); # resets the transaction depth
643 my ($self, $op, $extra_bind, $ident, @args) = @_;
644 my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
645 unshift(@bind, @$extra_bind) if $extra_bind;
647 my @debug_bind = map { defined $_ ? qq{'$_'} : q{'NULL'} } @bind;
648 $self->debugobj->query_start($sql, @debug_bind);
650 my $sth = eval { $self->sth($sql,$op) };
653 $self->throw_exception(
654 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
657 @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
661 $rv = eval { $sth->execute(@bind) };
664 $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
667 $self->throw_exception("'$sql' did not generate a statement.");
670 my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
671 $self->debugobj->query_end($sql, @debug_bind);
673 return (wantarray ? ($rv, $sth, @bind) : $rv);
677 my ($self, $ident, $to_insert) = @_;
678 $self->throw_exception(
679 "Couldn't insert ".join(', ',
680 map "$_ => $to_insert->{$_}", keys %$to_insert
682 ) unless ($self->_execute('insert' => [], $ident, $to_insert));
687 return shift->_execute('update' => [], @_);
691 return shift->_execute('delete' => [], @_);
695 my ($self, $ident, $select, $condition, $attrs) = @_;
696 my $order = $attrs->{order_by};
697 if (ref $condition eq 'SCALAR') {
698 $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
700 if (exists $attrs->{group_by} || $attrs->{having}) {
702 group_by => $attrs->{group_by},
703 having => $attrs->{having},
704 ($order ? (order_by => $order) : ())
707 my @args = ('select', $attrs->{bind}, $ident, $select, $condition, $order);
708 if ($attrs->{software_limit} ||
709 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
710 $attrs->{software_limit} = 1;
712 $self->throw_exception("rows attribute must be positive if present")
713 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
714 push @args, $attrs->{rows}, $attrs->{offset};
716 return $self->_execute(@args);
721 Handle a SQL select statement.
727 my ($ident, $select, $condition, $attrs) = @_;
728 return $self->cursor->new($self, \@_, $attrs);
733 Performs a select, fetch and return of data - handles a single row
738 # Need to call finish() to work round broken DBDs
742 my ($rv, $sth, @bind) = $self->_select(@_);
743 my @row = $sth->fetchrow_array;
750 Returns a L<DBI> sth (statement handle) for the supplied SQL.
755 my ($self, $sql) = @_;
756 # 3 is the if_active parameter which avoids active sth re-use
757 return $self->dbh->prepare_cached($sql, {}, 3);
760 =head2 columns_info_for
762 Returns database type info for a given table columns.
766 sub columns_info_for {
767 my ($self, $table) = @_;
769 my $dbh = $self->dbh;
771 if ($dbh->can('column_info')) {
773 my $old_raise_err = $dbh->{RaiseError};
774 my $old_print_err = $dbh->{PrintError};
775 $dbh->{RaiseError} = 1;
776 $dbh->{PrintError} = 0;
778 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
779 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
781 while ( my $info = $sth->fetchrow_hashref() ){
783 $column_info{data_type} = $info->{TYPE_NAME};
784 $column_info{size} = $info->{COLUMN_SIZE};
785 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
786 $column_info{default_value} = $info->{COLUMN_DEF};
787 my $col_name = $info->{COLUMN_NAME};
788 $col_name =~ s/^\"(.*)\"$/$1/;
790 $result{$col_name} = \%column_info;
793 $dbh->{RaiseError} = $old_raise_err;
794 $dbh->{PrintError} = $old_print_err;
795 return \%result if !$@;
799 my $sth = $dbh->prepare("SELECT * FROM $table WHERE 1=0");
801 my @columns = @{$sth->{NAME_lc}};
802 for my $i ( 0 .. $#columns ){
804 my $type_num = $sth->{TYPE}->[$i];
806 if(defined $type_num && $dbh->can('type_info')) {
807 my $type_info = $dbh->type_info($type_num);
808 $type_name = $type_info->{TYPE_NAME} if $type_info;
810 $column_info{data_type} = $type_name ? $type_name : $type_num;
811 $column_info{size} = $sth->{PRECISION}->[$i];
812 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
814 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
815 $column_info{data_type} = $1;
816 $column_info{size} = $2;
819 $result{$columns[$i]} = \%column_info;
825 =head2 last_insert_id
827 Return the row id of the last insert.
832 my ($self, $row) = @_;
834 return $self->dbh->func('last_insert_rowid');
840 Returns the database driver name.
844 sub sqlt_type { shift->dbh->{Driver}->{Name} }
846 =head2 create_ddl_dir (EXPERIMENTAL)
850 =item Arguments: $schema \@databases, $version, $directory, $sqlt_args
854 Creates an SQL file based on the Schema, for each of the specified
855 database types, in the given directory.
857 Note that this feature is currently EXPERIMENTAL and may not work correctly
858 across all databases, or fully handle complex relationships.
864 my ($self, $schema, $databases, $version, $dir, $sqltargs) = @_;
866 if(!$dir || !-d $dir)
868 warn "No directory given, using ./\n";
871 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
872 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
873 $version ||= $schema->VERSION || '1.x';
875 eval "use SQL::Translator";
876 $self->throw_exception("Can't deploy without SQL::Translator: $@") if $@;
878 my $sqlt = SQL::Translator->new({
882 foreach my $db (@$databases)
885 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
886 # $sqlt->parser_args({'DBIx::Class' => $schema);
887 $sqlt->data($schema);
888 $sqlt->producer($db);
891 my $filename = $schema->ddl_filename($db, $dir, $version);
894 $self->throw_exception("$filename already exists, skipping $db");
897 open($file, ">$filename")
898 or $self->throw_exception("Can't open $filename for writing ($!)");
899 my $output = $sqlt->translate;
901 # print join(":", keys %{$schema->source_registrations});
902 # print Dumper($sqlt->schema);
905 $self->throw_exception("Failed to translate to $db. (" . $sqlt->error . ")");
914 =head2 deployment_statements
916 Create the statements for L</deploy> and
917 L<DBIx::Class::Schema/deploy>.
921 sub deployment_statements {
922 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
923 # Need to be connected to get the correct sqlt_type
924 $self->ensure_connected() unless $type;
925 $type ||= $self->sqlt_type;
926 $version ||= $schema->VERSION || '1.x';
928 eval "use SQL::Translator";
931 eval "use SQL::Translator::Parser::DBIx::Class;";
932 $self->throw_exception($@) if $@;
933 eval "use SQL::Translator::Producer::${type};";
934 $self->throw_exception($@) if $@;
935 my $tr = SQL::Translator->new(%$sqltargs);
936 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
937 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
940 my $filename = $schema->ddl_filename($type, $dir, $version);
943 # $schema->create_ddl_dir([ $type ], $version, $dir, $sqltargs);
944 $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
948 open($file, "<$filename")
949 or $self->throw_exception("Can't open $filename ($!)");
953 return join('', @rows);
959 Sends the appropriate statements to create or modify tables to the
960 db. This would normally be called through
961 L<DBIx::Class::Schema/deploy>.
966 my ($self, $schema, $type, $sqltargs) = @_;
967 foreach my $statement ( $self->deployment_statements($schema, $type, undef, undef, $sqltargs) ) {
968 for ( split(";\n", $statement)) {
969 next if($_ =~ /^--/);
971 # next if($_ =~ /^DROP/m);
972 next if($_ =~ /^BEGIN TRANSACTION/m);
973 next if($_ =~ /^COMMIT/m);
974 $self->debugobj->query_start($_) if $self->debug;
975 $self->dbh->do($_) or warn "SQL was:\n $_";
976 $self->debugobj->query_end($_) if $self->debug;
981 =head2 datetime_parser
983 Returns the datetime parser class
987 sub datetime_parser {
989 return $self->{datetime_parser} ||= $self->build_datetime_parser(@_);
992 =head2 datetime_parser_type
994 Defines (returns) the datetime parser class - currently hardwired to
995 L<DateTime::Format::MySQL>
999 sub datetime_parser_type { "DateTime::Format::MySQL"; }
1001 =head2 build_datetime_parser
1003 See L</datetime_parser>
1007 sub build_datetime_parser {
1009 my $type = $self->datetime_parser_type(@_);
1011 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1015 sub DESTROY { shift->disconnect }
1021 The module defines a set of methods within the DBIC::SQL::Abstract
1022 namespace. These build on L<SQL::Abstract::Limit> to provide the
1023 SQL query functions.
1025 The following methods are extended:-
1039 Accessor for setting limit dialect. This is useful
1040 for JDBC-bridge among others where the remote SQL-dialect cannot
1041 be determined by the name of the driver alone.
1043 This option can also be set via L</connect_info>.
1047 Specifies what characters to use to quote table and column names. If
1048 you use this you will want to specify L<name_sep> as well.
1050 quote_char expectes either a single character, in which case is it is placed
1051 on either side of the table/column, or an arrayref of length 2 in which case the
1052 table/column name is placed between the elements.
1054 For example under MySQL you'd use C<quote_char('`')>, and user SQL Server you'd
1055 use C<quote_char(qw/[ ]/)>.
1057 This option can also be set via L</connect_info>.
1061 This only needs to be used in conjunction with L<quote_char>, and is used to
1062 specify the charecter that seperates elements (schemas, tables, columns) from
1063 each other. In most cases this is simply a C<.>.
1065 This option can also be set via L</connect_info>.
1069 =head1 ENVIRONMENT VARIABLES
1073 If C<DBIC_TRACE> is set then SQL trace information
1074 is produced (as when the L<debug> method is set).
1076 If the value is of the form C<1=/path/name> then the trace output is
1077 written to the file C</path/name>.
1079 This environment variable is checked when the storage object is first
1080 created (when you call connect on your schema). So, run-time changes
1081 to this environment variable will not take effect unless you also
1082 re-connect on your schema.
1084 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
1086 Old name for DBIC_TRACE
1090 Matt S. Trout <mst@shadowcatsystems.co.uk>
1092 Andy Grundman <andy@hybridized.org>
1096 You may distribute this code under the same terms as Perl itself.