.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "DBIx::Introspector::Advent 3pm" .TH DBIx::Introspector::Advent 3pm "2022-06-13" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" DBIx::Introspector::Advent \- Original Announcement of ::ResultSet::DateMethods1 .SH "VERSION" .IX Header "VERSION" version 0.001005 .SH "Content" .IX Header "Content" .SH "TEXT" .IX Header "TEXT" A common (but rarely acknowledged) problem when writing portable \s-1SQL\s0 is accurately detecting what kind of database you are connected to, and sometimes how you have connected. The typical solution is to assume that your database driver has a one-to-one mapping to your database. This works for many cases, for example many people only use \f(CW\*(C`DBD::mysql\*(C'\fR to connect to mysql, \f(CW\*(C`DBD::Pg\*(C'\fR to connect to Postgres, and \f(CW\*(C`DBD::SQLite\*(C'\fR to connect to SQLite. .PP The problem comes when you use a more generic driver. For example \&\f(CW\*(C`DBD::ODBC\*(C'\fR can connect to any database that supports \s-1ODBC\s0 (which includes mysql, Postgres, Oracle, and probably most importantly \s-1SQL\s0 Server.) Often users assume that \s-1ODBC\s0 means \s-1SQL\s0 Server but that's clearly not correct. .PP \&\f(CW\*(C`DBIx::Introspector\*(C'\fR solves this problem (as well as one other.) It has a basic but mostly complete set of detection methods. If, after it is released, there are problems discovered in the detection methods, the user can easily swap in new detection methods. The other feature that \&\f(CW\*(C`DBIx::Introspector\*(C'\fR gives the user is a way to query database handles (or \s-1DSN\s0's) for various pieces of information. .SS "How can I use it?" .IX Subsection "How can I use it?" For starters, you need to define a new \f(CW\*(C`DBIx::Introspector\*(C'\fR. Let's pretend we are writing some program that needs to concatenate stuff in the database, and should support some major databases. This code would probably be sufficient: .PP .Vb 1 \& my $d = DBIx::Introspector\->new(drivers => \*(Aq2013\-12.01\*(Aq); \& \& # standard dialects \& $d\->decorate_driver_unconnected(Pg => concat_sql => \*(Aq? || ?\*(Aq); \& $d\->decorate_driver_unconnected(SQLite => concat_sql => \*(Aq? || ?\*(Aq); \& \& # non\-standard \& $d\->decorate_driver_unconnected(MSSQL => concat_sql => \*(Aq? + ?\*(Aq); \& $d\->decorate_driver_unconnected(mysql => concat_sql => \*(AqCONCAT( ?, ? )\*(Aq); .Ve .PP First, note that we specify a string (\f(CW\*(C`2013\-12.01\*(C'\fR) for drivers. In order to maintain backwards compatibility \f(CW\*(C`DBIx::Introspector\*(C'\fR forces the user to request a driver set. Currently just one set exists, which attempts to match what DBIx::Class does internally at the time of release. .PP Next, the \f(CW\*(C`decorate_driver_unconnected\*(C'\fR call; \*(L"unconnected\*(R" is because these facts could be determined whether we were connected to the database or not. An example of a connected fact might be the following: .PP .Vb 6 \& $d\->decorate_driver_connected( \& MSSQL => full_version => sub { \& my ($ret) = $_[1]\->selectcol_arrayref(\*(AqSELECT @@VERSION\*(Aq); \& return $ret \& }, \& ); .Ve .PP The above code uses a connected \f(CW\*(C`dbh\*(C'\fR to ask \s-1SQL\s0 Server what the versions are of the database, \s-1OS,\s0 patchlevel, etc. .PP Note that because this is basically a bespoke prototypical object system you can easily add and replace drivers: .PP .Vb 10 \& $d\->replace_driver({ \& name => \*(AqMSSQL\*(Aq, \& connected_determination_strategy => sub { \& my %to = ( \& 11 => \*(Aq2012\*(Aq, \& 10 => \*(Aq2008\*(Aq, \& 9 => \*(Aq2005\*(Aq, \& ); \& my ($ver) = \& $_[1]\->selectcol_arrayref(q(SELECT SERVERPROPERTY(\*(AqProductVersion\*(Aq))); \& my ($major) = $ver =~ m/^(\ed+)\e./; \& my $to = $to{$ver} || \*(Aq\-OlderThanDirt\*(Aq, # or newer, but it\*(Aqs a demo \& return "MSSQL$to" \& }, \& }); \& \& $d\->add_driver($_) for qw({ \& name => \*(AqMSSQL2000\*(Aq, \& unconnected_options => { pagination_method => \*(Aqtop\*(Aq }, \& },{ \& name => \*(AqMSSQL2005\*(Aq, \& unconnected_options => { pagination_method => \*(Aqrno\*(Aq }, \& },{ \& name => \*(AqMSSQL2008\*(Aq, \& unconnected_options => { pagination_method => \*(Aqrno\*(Aq }, \& },{ \& name => \*(AqMSSQL2012\*(Aq, \& unconnected_options => { pagination_method => \*(Aqsql2012\*(Aq }, \& },{ \& name => \*(AqMSSQL\-OlderThanDirt\*(Aq, \& # documentation doesn\*(Aqt get this old, so who knows! \& }); .Ve .PP This code replaces the \s-1MSSQL\s0 driver with one that has another layer of detection based on version, and then adds drivers for each (sensible) version. The \&\f(CW\*(C`unconnected_options\*(C'\fR define a known pagination methods for reasonably recent versions of \s-1SQL\s0 Server. .SS "What's next?" .IX Subsection "What's next?" For \f(CW\*(C`DBIx::Introspector\*(C'\fR, there are probably more drivers that could be defined. Additionally a standard set of facts would be very handy. Caching the detection might be worthwhile, but I'd rather wait until someone notices a speed issue before doing that. .PP On top of that, a number of doors are opened by \f(CW\*(C`DBIx::Introspector\*(C'\fR. For example, the long dormant DBIx::Exceptions has been blocking on exactly this problem. Furthermore a number of already existing modules could be improved by the use of \&\f(CW\*(C`DBIx::Introspector\*(C'\fR, most notably DBIx::Connector, which doesn't work for anything using \s-1ODBC, ADO,\s0 and other non-one-to-one drives. .SH "AUTHOR" .IX Header "AUTHOR" Arthur Axel \*(L"fREW\*(R" Schmidt .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2015 by Arthur Axel \*(L"fREW\*(R" Schmidt. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.