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());
259 if (defined($ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}) &&
260 ($ENV{DBIX_CLASS_STORAGE_DBI_DEBUG} =~ /=(.+)$/)) {
261 $fh = IO::File->new($1, 'w')
262 or $new->throw_exception("Cannot open trace file $1");
264 $fh = IO::File->new('>&STDERR');
267 $new->debug(1) if $ENV{DBIX_CLASS_STORAGE_DBI_DEBUG};
271 =head2 throw_exception
273 Throws an exception - croaks.
277 sub throw_exception {
278 my ($self, $msg) = @_;
284 The arguments of C<connect_info> are always a single array reference.
286 This is normally accessed via L<DBIx::Class::Schema/connection>, which
287 encapsulates its argument list in an arrayref before calling
288 C<connect_info> here.
290 The arrayref can either contain the same set of arguments one would
291 normally pass to L<DBI/connect>, or a lone code reference which returns
292 a connected database handle.
294 In either case, there is an optional final element within the arrayref
295 which can hold a hashref of connection-specific Storage::DBI options.
296 These include C<on_connect_do>, and the sql_maker options
297 C<limit_dialect>, C<quote_char>, and C<name_sep>. Examples:
299 ->connect_info([ 'dbi:SQLite:./foo.db' ]);
301 ->connect_info([ sub { DBI->connect(...) } ]);
309 { quote_char => q{`}, name_sep => q{@} },
315 sub { DBI->connect(...) },
316 { quote_char => q{`}, name_sep => q{@} },
322 $schema->storage->on_connect_do(['PRAGMA synchronous = OFF']);
324 Call this after C<< $schema->connect >> to have the sql statements
325 given executed on every db connect.
327 This option can also be set via L</connect_info>.
331 Causes SQL trace information to be emitted on the C<debugobj> object.
332 (or C<STDERR> if C<debugobj> has not specifically been set).
336 Set or retrieve the filehandle used for trace/debug output. This should be
337 an IO::Handle compatible ojbect (only the C<print> method is used. Initially
338 set to be STDERR - although see information on the
339 L<DBIX_CLASS_STORAGE_DBI_DEBUG> environment variable.
346 if ($self->debugobj->can('debugfh')) {
347 return $self->debugobj->debugfh(@_);
353 Sets or retrieves the object used for metric collection. Defaults to an instance
354 of L<DBIx::Class::Storage::Statistics> that is campatible with the original
355 method of using a coderef as a callback. See the aforementioned Statistics
356 class for more information.
360 Sets a callback to be executed each time a statement is run; takes a sub
361 reference. Callback is executed as $sub->($op, $info) where $op is
362 SELECT/INSERT/UPDATE/DELETE and $info is what would normally be printed.
364 See L<debugobj> for a better way.
371 if ($self->debugobj->can('callback')) {
372 return $self->debugobj->callback(@_);
378 Disconnect the L<DBI> handle, performing a rollback first if the
379 database is not in C<AutoCommit> mode.
386 if( $self->connected ) {
387 $self->_dbh->rollback unless $self->_dbh->{AutoCommit};
388 $self->_dbh->disconnect;
395 Check if the L<DBI> handle is connected. Returns true if the handle
400 sub connected { my ($self) = @_;
402 if(my $dbh = $self->_dbh) {
403 if(defined $self->_conn_tid && $self->_conn_tid != threads->tid) {
404 $self->_sql_maker(undef);
405 return $self->_dbh(undef);
407 elsif($self->_conn_pid != $$) {
408 $self->_dbh->{InactiveDestroy} = 1;
409 $self->_sql_maker(undef);
410 return $self->_dbh(undef)
412 return ($dbh->FETCH('Active') && $dbh->ping);
418 =head2 ensure_connected
420 Check whether the database handle is connected - if not then make a
425 sub ensure_connected {
428 unless ($self->connected) {
429 $self->_populate_dbh;
435 Returns the dbh - a data base handle of class L<DBI>.
442 $self->ensure_connected;
446 sub _sql_maker_args {
449 return ( limit_dialect => $self->dbh );
454 Returns a C<sql_maker> object - normally an object of class
455 C<DBIC::SQL::Abstract>.
461 unless ($self->_sql_maker) {
462 $self->_sql_maker(new DBIC::SQL::Abstract( $self->_sql_maker_args ));
464 return $self->_sql_maker;
468 my ($self, $info_arg) = @_;
472 my $info = [ @$info_arg ]; # copy because we can alter it
473 my $last_info = $info->[-1];
474 if(ref $last_info eq 'HASH') {
476 if(my $on_connect_do = $last_info->{on_connect_do}) {
478 $self->on_connect_do($on_connect_do);
480 for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
481 if(my $opt_val = $last_info->{$sql_maker_opt}) {
483 $sql_maker_opts{$sql_maker_opt} = $opt_val;
487 # remove our options hashref if it was there, to avoid confusing
488 # DBI in the case the user didn't use all 4 DBI options, as in:
489 # [ 'dbi:SQLite:foo.db', { quote_char => q{`} } ]
490 pop(@$info) if $used;
493 $self->_connect_info($info);
494 $self->sql_maker->$_($sql_maker_opts{$_}) for(keys %sql_maker_opts);
497 $self->_connect_info;
502 my @info = @{$self->_connect_info || []};
503 $self->_dbh($self->_connect(@info));
505 if(ref $self eq 'DBIx::Class::Storage::DBI') {
506 my $driver = $self->_dbh->{Driver}->{Name};
507 if ($self->load_optional_class("DBIx::Class::Storage::DBI::${driver}")) {
508 bless $self, "DBIx::Class::Storage::DBI::${driver}";
509 $self->_rebless() if $self->can('_rebless');
513 # if on-connect sql statements are given execute them
514 foreach my $sql_statement (@{$self->on_connect_do || []}) {
515 $self->debugobj->query_start($sql_statement) if $self->debug();
516 $self->_dbh->do($sql_statement);
517 $self->debugobj->query_end($sql_statement) if $self->debug();
520 $self->_conn_pid($$);
521 $self->_conn_tid(threads->tid) if $INC{'threads.pm'};
525 my ($self, @info) = @_;
527 $self->throw_exception("You failed to provide any connection info")
530 my ($old_connect_via, $dbh);
532 if ($INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}) {
533 $old_connect_via = $DBI::connect_via;
534 $DBI::connect_via = 'connect';
538 $dbh = ref $info[0] eq 'CODE'
540 : DBI->connect(@info);
543 $DBI::connect_via = $old_connect_via if $old_connect_via;
546 $self->throw_exception("DBI Connection failed: " . ($@ || $DBI::errstr));
554 Calls begin_work on the current dbh.
556 See L<DBIx::Class::Schema> for the txn_do() method, which allows for
557 an entire code block to be executed transactionally.
563 if ($self->{transaction_depth}++ == 0) {
564 my $dbh = $self->dbh;
565 if ($dbh->{AutoCommit}) {
566 $self->debugobj->txn_begin()
575 Issues a commit against the current dbh.
581 my $dbh = $self->dbh;
582 if ($self->{transaction_depth} == 0) {
583 unless ($dbh->{AutoCommit}) {
584 $self->debugobj->txn_commit()
590 if (--$self->{transaction_depth} == 0) {
591 $self->debugobj->txn_commit()
600 Issues a rollback against the current dbh. A nested rollback will
601 throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
602 which allows the rollback to propagate to the outermost transaction.
610 my $dbh = $self->dbh;
611 if ($self->{transaction_depth} == 0) {
612 unless ($dbh->{AutoCommit}) {
613 $self->debugobj->txn_rollback()
619 if (--$self->{transaction_depth} == 0) {
620 $self->debugobj->txn_rollback()
625 die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new;
632 my $exception_class = "DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION";
633 $error =~ /$exception_class/ and $self->throw_exception($error);
634 $self->{transaction_depth} = 0; # ensure that a failed rollback
635 $self->throw_exception($error); # resets the transaction depth
640 my ($self, $op, $extra_bind, $ident, @args) = @_;
641 my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
642 unshift(@bind, @$extra_bind) if $extra_bind;
644 my @debug_bind = map { defined $_ ? qq{'$_'} : q{'NULL'} } @bind;
645 $self->debugobj->query_start($sql, @debug_bind);
647 my $sth = eval { $self->sth($sql,$op) };
650 $self->throw_exception(
651 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"
654 @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args
658 $rv = eval { $sth->execute(@bind) };
661 $self->throw_exception("Error executing '$sql': ".($@ || $sth->errstr));
664 $self->throw_exception("'$sql' did not generate a statement.");
667 my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
668 $self->debugobj->query_end($sql, @debug_bind);
670 return (wantarray ? ($rv, $sth, @bind) : $rv);
674 my ($self, $ident, $to_insert) = @_;
675 $self->throw_exception(
676 "Couldn't insert ".join(', ',
677 map "$_ => $to_insert->{$_}", keys %$to_insert
679 ) unless ($self->_execute('insert' => [], $ident, $to_insert));
684 return shift->_execute('update' => [], @_);
688 return shift->_execute('delete' => [], @_);
692 my ($self, $ident, $select, $condition, $attrs) = @_;
693 my $order = $attrs->{order_by};
694 if (ref $condition eq 'SCALAR') {
695 $order = $1 if $$condition =~ s/ORDER BY (.*)$//i;
697 if (exists $attrs->{group_by} || $attrs->{having}) {
699 group_by => $attrs->{group_by},
700 having => $attrs->{having},
701 ($order ? (order_by => $order) : ())
704 my @args = ('select', $attrs->{bind}, $ident, $select, $condition, $order);
705 if ($attrs->{software_limit} ||
706 $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
707 $attrs->{software_limit} = 1;
709 $self->throw_exception("rows attribute must be positive if present")
710 if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
711 push @args, $attrs->{rows}, $attrs->{offset};
713 return $self->_execute(@args);
718 Handle a SQL select statement.
724 my ($ident, $select, $condition, $attrs) = @_;
725 return $self->cursor->new($self, \@_, $attrs);
730 Performs a select, fetch and return of data - handles a single row
735 # Need to call finish() to work round broken DBDs
739 my ($rv, $sth, @bind) = $self->_select(@_);
740 my @row = $sth->fetchrow_array;
747 Returns a L<DBI> sth (statement handle) for the supplied SQL.
752 my ($self, $sql) = @_;
753 # 3 is the if_active parameter which avoids active sth re-use
754 return $self->dbh->prepare_cached($sql, {}, 3);
757 =head2 columns_info_for
759 Returns database type info for a given table columns.
763 sub columns_info_for {
764 my ($self, $table) = @_;
766 my $dbh = $self->dbh;
768 if ($dbh->can('column_info')) {
770 my $old_raise_err = $dbh->{RaiseError};
771 my $old_print_err = $dbh->{PrintError};
772 $dbh->{RaiseError} = 1;
773 $dbh->{PrintError} = 0;
775 my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table);
776 my $sth = $dbh->column_info( undef,$schema, $tab, '%' );
778 while ( my $info = $sth->fetchrow_hashref() ){
780 $column_info{data_type} = $info->{TYPE_NAME};
781 $column_info{size} = $info->{COLUMN_SIZE};
782 $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
783 $column_info{default_value} = $info->{COLUMN_DEF};
784 my $col_name = $info->{COLUMN_NAME};
785 $col_name =~ s/^\"(.*)\"$/$1/;
787 $result{$col_name} = \%column_info;
790 $dbh->{RaiseError} = $old_raise_err;
791 $dbh->{PrintError} = $old_print_err;
792 return \%result if !$@;
796 my $sth = $dbh->prepare("SELECT * FROM $table WHERE 1=0");
798 my @columns = @{$sth->{NAME_lc}};
799 for my $i ( 0 .. $#columns ){
801 my $type_num = $sth->{TYPE}->[$i];
803 if(defined $type_num && $dbh->can('type_info')) {
804 my $type_info = $dbh->type_info($type_num);
805 $type_name = $type_info->{TYPE_NAME} if $type_info;
807 $column_info{data_type} = $type_name ? $type_name : $type_num;
808 $column_info{size} = $sth->{PRECISION}->[$i];
809 $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
811 if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) {
812 $column_info{data_type} = $1;
813 $column_info{size} = $2;
816 $result{$columns[$i]} = \%column_info;
822 =head2 last_insert_id
824 Return the row id of the last insert.
829 my ($self, $row) = @_;
831 return $self->dbh->func('last_insert_rowid');
837 Returns the database driver name.
841 sub sqlt_type { shift->dbh->{Driver}->{Name} }
843 =head2 create_ddl_dir (EXPERIMENTAL)
847 =item Arguments: $schema \@databases, $version, $directory, $sqlt_args
851 Creates an SQL file based on the Schema, for each of the specified
852 database types, in the given directory.
854 Note that this feature is currently EXPERIMENTAL and may not work correctly
855 across all databases, or fully handle complex relationships.
861 my ($self, $schema, $databases, $version, $dir, $sqltargs) = @_;
863 if(!$dir || !-d $dir)
865 warn "No directory given, using ./\n";
868 $databases ||= ['MySQL', 'SQLite', 'PostgreSQL'];
869 $databases = [ $databases ] if(ref($databases) ne 'ARRAY');
870 $version ||= $schema->VERSION || '1.x';
872 eval "use SQL::Translator";
873 $self->throw_exception("Can't deploy without SQL::Translator: $@") if $@;
875 my $sqlt = SQL::Translator->new({
879 foreach my $db (@$databases)
882 $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
883 # $sqlt->parser_args({'DBIx::Class' => $schema);
884 $sqlt->data($schema);
885 $sqlt->producer($db);
888 my $filename = $schema->ddl_filename($db, $dir, $version);
891 $self->throw_exception("$filename already exists, skipping $db");
894 open($file, ">$filename")
895 or $self->throw_exception("Can't open $filename for writing ($!)");
896 my $output = $sqlt->translate;
898 # print join(":", keys %{$schema->source_registrations});
899 # print Dumper($sqlt->schema);
902 $self->throw_exception("Failed to translate to $db. (" . $sqlt->error . ")");
911 =head2 deployment_statements
913 Create the statements for L</deploy> and
914 L<DBIx::Class::Schema/deploy>.
918 sub deployment_statements {
919 my ($self, $schema, $type, $version, $dir, $sqltargs) = @_;
920 # Need to be connected to get the correct sqlt_type
921 $self->ensure_connected() unless $type;
922 $type ||= $self->sqlt_type;
923 $version ||= $schema->VERSION || '1.x';
925 eval "use SQL::Translator";
928 eval "use SQL::Translator::Parser::DBIx::Class;";
929 $self->throw_exception($@) if $@;
930 eval "use SQL::Translator::Producer::${type};";
931 $self->throw_exception($@) if $@;
932 my $tr = SQL::Translator->new(%$sqltargs);
933 SQL::Translator::Parser::DBIx::Class::parse( $tr, $schema );
934 return "SQL::Translator::Producer::${type}"->can('produce')->($tr);
937 my $filename = $schema->ddl_filename($type, $dir, $version);
940 # $schema->create_ddl_dir([ $type ], $version, $dir, $sqltargs);
941 $self->throw_exception("No SQL::Translator, and no Schema file found, aborting deploy");
945 open($file, "<$filename")
946 or $self->throw_exception("Can't open $filename ($!)");
950 return join('', @rows);
956 Sends the appropriate statements to create or modify tables to the
957 db. This would normally be called through
958 L<DBIx::Class::Schema/deploy>.
963 my ($self, $schema, $type, $sqltargs) = @_;
964 foreach my $statement ( $self->deployment_statements($schema, $type, undef, undef, $sqltargs) ) {
965 for ( split(";\n", $statement)) {
966 next if($_ =~ /^--/);
968 # next if($_ =~ /^DROP/m);
969 next if($_ =~ /^BEGIN TRANSACTION/m);
970 next if($_ =~ /^COMMIT/m);
971 $self->debugobj->query_start($_) if $self->debug;
972 $self->dbh->do($_) or warn "SQL was:\n $_";
973 $self->debugobj->query_end($_) if $self->debug;
978 =head2 datetime_parser
980 Returns the datetime parser class
984 sub datetime_parser {
986 return $self->{datetime_parser} ||= $self->build_datetime_parser(@_);
989 =head2 datetime_parser_type
991 Defines (returns) the datetime parser class - currently hardwired to
992 L<DateTime::Format::MySQL>
996 sub datetime_parser_type { "DateTime::Format::MySQL"; }
998 =head2 build_datetime_parser
1000 See L</datetime_parser>
1004 sub build_datetime_parser {
1006 my $type = $self->datetime_parser_type(@_);
1008 $self->throw_exception("Couldn't load ${type}: $@") if $@;
1012 sub DESTROY { shift->disconnect }
1018 The module defines a set of methods within the DBIC::SQL::Abstract
1019 namespace. These build on L<SQL::Abstract::Limit> to provide the
1020 SQL query functions.
1022 The following methods are extended:-
1036 Accessor for setting limit dialect. This is useful
1037 for JDBC-bridge among others where the remote SQL-dialect cannot
1038 be determined by the name of the driver alone.
1040 This option can also be set via L</connect_info>.
1044 Specifies what characters to use to quote table and column names. If
1045 you use this you will want to specify L<name_sep> as well.
1047 quote_char expectes either a single character, in which case is it is placed
1048 on either side of the table/column, or an arrayref of length 2 in which case the
1049 table/column name is placed between the elements.
1051 For example under MySQL you'd use C<quote_char('`')>, and user SQL Server you'd
1052 use C<quote_char(qw/[ ]/)>.
1054 This option can also be set via L</connect_info>.
1058 This only needs to be used in conjunction with L<quote_char>, and is used to
1059 specify the charecter that seperates elements (schemas, tables, columns) from
1060 each other. In most cases this is simply a C<.>.
1062 This option can also be set via L</connect_info>.
1066 =head1 ENVIRONMENT VARIABLES
1068 =head2 DBIX_CLASS_STORAGE_DBI_DEBUG
1070 If C<DBIX_CLASS_STORAGE_DBI_DEBUG> is set then SQL trace information
1071 is produced (as when the L<debug> method is set).
1073 If the value is of the form C<1=/path/name> then the trace output is
1074 written to the file C</path/name>.
1076 This environment variable is checked when the storage object is first
1077 created (when you call connect on your schema). So, run-time changes
1078 to this environment variable will not take effect unless you also
1079 re-connect on your schema.
1083 Matt S. Trout <mst@shadowcatsystems.co.uk>
1085 Andy Grundman <andy@hybridized.org>
1089 You may distribute this code under the same terms as Perl itself.