You have _way_ too much free time Steffen! The only things that comes to mind are that there's a specific api call for require'ing a file that should be used to avoid static's and threading issues. And the return value probably needs to be made mortal (sv_2mortal(...)).
Tim. On Wed, Nov 28, 2001 at 02:09:55PM +0100, Steffen Goeldner wrote: > Tim Bunce wrote: > > > > On Mon, Nov 26, 2001 at 04:25:16PM +0100, Steffen Goeldner wrote: > > > > > > > else if (htype==DBIt_DB && strnEQ(key, "SQL_", 4)) { > > > /* XXX DBIt_ST ? */ > > > valuesv = dbih_get_info(h, key, keylen); > > > > That presumes that _all_ attributes begining with SQL_ are > > 'get_info' attributes. That may not be the case. I'd suggest > > > > else if (htype==DBIt_DB && strnEQ(key, "SQL_", 4) && gi_code = >get_info_name2code(key)) > > > > That's right! My brain was focused on get_info. However, > dbih_get_attr_k is big enough, I renamed dbih_get_info to > the more generic dbih_get_attr_k_sql_: > > else if (htype==DBIt_DB && strnEQ(key, "SQL_", 4)) { > valuesv = dbih_get_attr_k_sql_(h, keysv, key, keylen); > > and let it handle all SQL_* requests: > > static SV * > dbih_get_attr_k_sql_(SV *h, SV *keysv, char *key, STRLEN keylen) > { > dPERINTERP; > dSP; > HV *hv; > char *meth_name; > SV *valuesv; > static bool loaded = FALSE; > > if (!loaded) { > eval_pv("require DBI::Const", TRUE); > loaded = TRUE; > } > if ((hv = get_hv("DBI::Const::GetInfo", FALSE)) && hv_exists(hv, key, keylen)) { > meth_name = "get_info"; > } > /* > other SQL_* requests: > else if ((hv = get_hv("DBI::Const::Get???", FALSE)) && hv_exists(hv, key, >keylen)) { > meth_name = "get_???"; > } > */ > else { > croak("Can't get %s->{%s}: unrecognised attribute", neatsvpv(h,0), key); > } > > PUSHMARK(SP); > XPUSHs(h); > XPUSHs(keysv); > PUTBACK; > if (call_method(meth_name, G_SCALAR) != 1) > croak("Can't locate DBI object method \"%s\"", meth_name); > SPAGAIN; > valuesv = POPs; > PUTBACK; > > return newSVsv(valuesv); > } > > Comments are highly appreciated! > > > > Of course, dbih_get_info needs to be written. I think, it should > > > > > > 1) map the symbolic name to the numeric code > > > (via %DBI::Const::GetInfo?) > > > 2) call $dbh->get_info($code) > > > > There's also the question of whether each particular item of 'info' > > can be cached for the handle it's being called on (see cacheit in > > dbih_get_attr_k). > > > > Here I need further investigation ... > > > Yeap. Though you could argue that using hash fetching should be the > > primary API to get_info and just not bother supporting importing > > numeric constants. And I don't think there's a good performance > > argument for numeric constants. So lets just skip the import :) > > Great! > > For testing purposes, I added a few more lines of code to DBI, > see my attachment. > > > Steffen > diff -Nrc DBI-1.20.orig/DBI.xs DBI-1.20/DBI.xs > *** DBI-1.20.orig/DBI.xs Sat Aug 25 00:10:48 2001 > --- DBI-1.20/DBI.xs Wed Nov 28 10:33:59 2001 > *************** > *** 1243,1248 **** > --- 1243,1283 ---- > > > static SV * > + dbih_get_attr_k_sql_(SV *h, SV *keysv, char *key, STRLEN keylen) > + { > + dPERINTERP; > + dSP; > + HV *hv; > + char *meth_name; > + SV *valuesv; > + static bool loaded = FALSE; > + > + if (!loaded) { > + eval_pv("require DBI::Const", TRUE); > + loaded = TRUE; > + } > + if ((hv = get_hv("DBI::Const::GetInfo", FALSE)) && hv_exists(hv, key, keylen)) >{ > + meth_name = "get_info"; > + } > + else { > + croak("Can't get %s->{%s}: unrecognised attribute", neatsvpv(h,0), key); > + } > + > + PUSHMARK(SP); > + XPUSHs(h); > + XPUSHs(keysv); > + PUTBACK; > + if (call_method(meth_name, G_SCALAR) != 1) > + croak("Can't locate DBI object method \"%s\"", meth_name); > + SPAGAIN; > + valuesv = POPs; > + PUTBACK; > + > + return newSVsv(valuesv); > + } > + > + > + static SV * > dbih_get_attr_k(h, keysv, dbikey) /* XXX split into dr/db/st >funcs */ > SV *h; > SV *keysv; > *************** > *** 1406,1411 **** > --- 1441,1449 ---- > } > else if (keylen==9 && strEQ(key, "BegunWork")) { > valuesv = boolSV(DBIc_has(imp_xxh,DBIcf_BegunWork)); > + } > + else if (htype==DBIt_DB && strnEQ(key, "SQL_", 4)) { > + valuesv = dbih_get_attr_k_sql_(h, keysv, key, keylen); > } > else { /* finally check the actual hash just in case */ > svp = hv_fetch((HV*)SvRV(h), key, keylen, FALSE); > diff -Nrc DBI-1.20.orig/lib/DBD/NullP.pm DBI-1.20/lib/DBD/NullP.pm > *** DBI-1.20.orig/lib/DBD/NullP.pm Sat Aug 25 00:10:50 2001 > --- DBI-1.20/lib/DBD/NullP.pm Wed Nov 28 10:30:41 2001 > *************** > *** 58,63 **** > --- 58,69 ---- > $outer; > } > > + sub get_info { > + my $dbh = shift; > + my $git = shift; > + return 'GetInfo: ' . $git; > + } > + > sub FETCH { > my ($dbh, $attrib) = @_; > # In reality this would interrogate the database engine to > diff -Nrc DBI-1.20.orig/lib/DBI/Const.pm DBI-1.20/lib/DBI/Const.pm > *** DBI-1.20.orig/lib/DBI/Const.pm Thu Jan 01 01:00:00 1970 > --- DBI-1.20/lib/DBI/Const.pm Wed Nov 28 10:28:48 2001 > *************** > *** 0 **** > --- 1,238 ---- > + package DBI::Const; > + > + =head1 NAME > + > + DBI::Const - DBI constants > + > + =cut > + > + $VERSION = '0.01'; > + > + %GetInfo = > + ( # ODBC SQL > + SQL_ACTIVE_CONNECTIONS => 0 # 0 > + , SQL_MAXIMUM_DRIVER_CONNECTIONS => 0 # 0 0 > + , SQL_MAX_DRIVER_CONNECTIONS => 0 # 0 > + , SQL_INFO_FIRST => 0 # 0 > + , SQL_ACTIVE_STATEMENTS => 1 # 1 > + , SQL_MAX_CONCURRENT_ACTIVITIES => 1 # 1 > + , SQL_MAXIMUM_CONCURRENT_ACTIVITIES => 1 # 1 1 > + , SQL_DATA_SOURCE_NAME => 2 # 2 2 > + , SQL_DRIVER_HDBC => 3 # 3 > + , SQL_DRIVER_HENV => 4 # 4 > + , SQL_DRIVER_HSTMT => 5 # 5 > + , SQL_DRIVER_NAME => 6 # 6 > + , SQL_DRIVER_VER => 7 # 7 > + , SQL_FETCH_DIRECTION => 8 # 8 8 > + , SQL_ODBC_API_CONFORMANCE => 9 # 9 > + , SQL_ODBC_VER => 10 # 10 > + , SQL_ROW_UPDATES => 11 # 11 > + , SQL_ODBC_SAG_CLI_CONFORMANCE => 12 # 12 > + , SQL_SERVER_NAME => 13 # 13 13 > + , SQL_SEARCH_PATTERN_ESCAPE => 14 # 14 14 > + , SQL_ODBC_SQL_CONFORMANCE => 15 # 15 > + , SQL_DBMS_NAME => 17 # 17 17 > + , SQL_DBMS_VER => 18 # 18 > + , SQL_DBMS_VERSION => 18 # 18 > + , SQL_ACCESSIBLE_TABLES => 19 # 19 > + , SQL_ACCESSIBLE_PROCEDURES => 20 # 20 > + , SQL_PROCEDURES => 21 # 21 > + , SQL_CONCAT_NULL_BEHAVIOR => 22 # 22 > + , SQL_CURSOR_COMMIT_BEHAVIOR => 23 # 23 23 > + , SQL_CURSOR_ROLLBACK_BEHAVIOR => 24 # 24 > + , SQL_DATA_SOURCE_READ_ONLY => 25 # 25 25 > + , SQL_DEFAULT_TXN_ISOLATION => 26 # 26 > + , SQL_DEFAULT_TRANSACTION_ISOLATION => 26 # 26 > + , SQL_EXPRESSIONS_IN_ORDERBY => 27 # 27 > + , SQL_IDENTIFIER_CASE => 28 # 28 28 > + , SQL_IDENTIFIER_QUOTE_CHAR => 29 # 29 > + , SQL_MAXIMUM_COLUMN_NAME_LENGTH => 30 # 30 30 > + , SQL_MAX_COLUMN_NAME_LEN => 30 # 30 > + , SQL_MAXIMUM_CURSOR_NAME_LENGTH => 31 # 31 31 > + , SQL_MAX_CURSOR_NAME_LEN => 31 # 31 > + , SQL_MAX_OWNER_NAME_LEN => 32 # 32 > + , SQL_MAXIMUM_SCHEMA_NAME_LENGTH => 32 # 32 32 > + , SQL_MAX_SCHEMA_NAME_LEN => 32 # 32 > + , SQL_MAX_PROCEDURE_NAME_LEN => 33 # 33 > + , SQL_MAX_CATALOG_NAME_LEN => 34 # 34 > + , SQL_MAXIMUM_CATALOG_NAME_LENGTH => 34 # 34 34 > + , SQL_MAX_QUALIFIER_NAME_LEN => 34 # 34 > + , SQL_MAX_TABLE_NAME_LEN => 35 # 35 > + , SQL_MAXIMUM_TABLE_NAME_LENGTH => 35 # 35 > + , SQL_MULT_RESULT_SETS => 36 # 36 > + , SQL_MULTIPLE_ACTIVE_TXN => 37 # 37 > + , SQL_OUTER_JOINS => 38 # 38 > + , SQL_OWNER_TERM => 39 # 39 > + , SQL_SCHEMA_TERM => 39 # 39 > + , SQL_PROCEDURE_TERM => 40 # 40 > + , SQL_CATALOG_NAME_SEPARATOR => 41 # 41 > + , SQL_QUALIFIER_NAME_SEPARATOR => 41 # 41 > + , SQL_QUALIFIER_TERM => 42 # 42 > + , SQL_CATALOG_TERM => 42 # 42 > + , SQL_SCROLL_CONCURRENCY => 43 # 43 43 > + , SQL_SCROLL_OPTIONS => 44 # 44 > + , SQL_TABLE_TERM => 45 # 45 > + , SQL_TXN_CAPABLE => 46 # 46 > + , SQL_TRANSACTION_CAPABLE => 46 # 46 46 > + , SQL_USER_NAME => 47 # 47 47 > + , SQL_CONVERT_FUNCTIONS => 48 # 48 > + , SQL_NUMERIC_FUNCTIONS => 49 # 49 > + , SQL_STRING_FUNCTIONS => 50 # 50 > + , SQL_SYSTEM_FUNCTIONS => 51 # 51 > + , SQL_TIMEDATE_FUNCTIONS => 52 # 52 > + , SQL_CONVERT_BIGINT => 53 # 53 > + , SQL_CONVERT_BINARY => 54 # 54 > + , SQL_CONVERT_BIT => 55 # 55 > + , SQL_CONVERT_CHAR => 56 # 56 > + , SQL_CONVERT_DATE => 57 # 57 > + , SQL_CONVERT_DECIMAL => 58 # 58 > + , SQL_CONVERT_DOUBLE => 59 # 59 > + , SQL_CONVERT_FLOAT => 60 # 60 > + , SQL_CONVERT_INTEGER => 61 # 61 > + , SQL_CONVERT_LONGVARCHAR => 62 # 62 > + , SQL_CONVERT_NUMERIC => 63 # 63 > + , SQL_CONVERT_REAL => 64 # 64 > + , SQL_CONVERT_SMALLINT => 65 # 65 > + , SQL_CONVERT_TIME => 66 # 66 > + , SQL_CONVERT_TIMESTAMP => 67 # 67 > + , SQL_CONVERT_TINYINT => 68 # 68 > + , SQL_CONVERT_VARBINARY => 69 # 69 > + , SQL_CONVERT_VARCHAR => 70 # 70 > + , SQL_CONVERT_LONGVARBINARY => 71 # 71 > + , SQL_TXN_ISOLATION_OPTION => 72 # 72 > + , SQL_TRANSACTION_ISOLATION_OPTION => 72 # 72 72 > + , SQL_INTEGRITY => 73 # 73 73 > + , SQL_ODBC_SQL_OPT_IEF => 73 # 73 > + , SQL_CORRELATION_NAME => 74 # 74 > + , SQL_NON_NULLABLE_COLUMNS => 75 # 75 > + , SQL_DRIVER_HLIB => 76 # 76 > + , SQL_DRIVER_ODBC_VER => 77 # 77 > + , SQL_LOCK_TYPES => 78 # 78 > + , SQL_POS_OPERATIONS => 79 # 79 > + , SQL_POSITIONED_STATEMENTS => 80 # 80 > + , SQL_GETDATA_EXTENSIONS => 81 # 81 81 > + , SQL_BOOKMARK_PERSISTENCE => 82 # 82 > + , SQL_STATIC_SENSITIVITY => 83 # 83 > + , SQL_FILE_USAGE => 84 # 84 > + , SQL_NULL_COLLATION => 85 # 85 85 > + , SQL_ALTER_TABLE => 86 # 86 86 > + , SQL_COLUMN_ALIAS => 87 # 87 > + , SQL_GROUP_BY => 88 # 88 > + , SQL_KEYWORDS => 89 # 89 > + , SQL_ORDER_BY_COLUMNS_IN_SELECT => 90 # 90 90 > + , SQL_OWNER_USAGE => 91 # 91 > + , SQL_SCHEMA_USAGE => 91 # 91 > + , SQL_QUALIFIER_USAGE => 92 # 92 > + , SQL_CATALOG_USAGE => 92 # 92 > + , SQL_QUOTED_IDENTIFIER_CASE => 93 # 93 > + , SQL_SPECIAL_CHARACTERS => 94 # 94 94 > + , SQL_SUBQUERIES => 95 # 95 > + , SQL_UNION_STATEMENT => 96 # 96 > + , SQL_UNION => 96 # 96 > + , SQL_MAXIMUM_COLUMNS_IN_GROUP_BY => 97 # 97 97 > + , SQL_MAX_COLUMNS_IN_GROUP_BY => 97 # 97 > + , SQL_MAXIMUM_COLUMNS_IN_INDEX => 98 # 98 > + , SQL_MAX_COLUMNS_IN_INDEX => 98 # 98 > + , SQL_MAX_COLUMNS_IN_ORDER_BY => 99 # 99 > + , SQL_MAXIMUM_COLUMNS_IN_ORDER_BY => 99 # 99 99 > + , SQL_MAX_COLUMNS_IN_SELECT => 100 # 100 > + , SQL_MAXIMUM_COLUMNS_IN_SELECT => 100 # 100 100 > + , SQL_MAXIMUM_COLUMNS_IN_TABLE => 101 # 101 > + , SQL_MAX_COLUMNS_IN_TABLE => 101 # 101 > + , SQL_MAXIMUM_INDEX_SIZE => 102 # 102 > + , SQL_MAX_INDEX_SIZE => 102 # 102 > + , SQL_MAX_ROW_SIZE_INCLUDES_LONG => 103 # 103 > + , SQL_MAX_ROW_SIZE => 104 # 104 > + , SQL_MAXIMUM_ROW_SIZE => 104 # 104 > + , SQL_MAX_STATEMENT_LEN => 105 # 105 > + , SQL_MAXIMUM_STATEMENT_LENGTH => 105 # 105 > + , SQL_MAXIMUM_TABLES_IN_SELECT => 106 # 106 106 > + , SQL_MAX_TABLES_IN_SELECT => 106 # 106 > + , SQL_MAX_USER_NAME_LEN => 107 # 107 > + , SQL_MAXIMUM_USER_NAME_LENGTH => 107 # 107 107 > + , SQL_MAX_CHAR_LITERAL_LEN => 108 # 108 > + , SQL_TIMEDATE_ADD_INTERVALS => 109 # 109 > + , SQL_TIMEDATE_DIFF_INTERVALS => 110 # 110 > + , SQL_NEED_LONG_DATA_LEN => 111 # 111 > + , SQL_MAX_BINARY_LITERAL_LEN => 112 # 112 > + , SQL_LIKE_ESCAPE_CLAUSE => 113 # 113 > + , SQL_INFO_LAST => 114 # 114 > + , SQL_QUALIFIER_LOCATION => 114 # 114 > + , SQL_CATALOG_LOCATION => 114 # 114 > + , SQL_OUTER_JOIN_CAPABILITIES => 115 # 115 115 > + , SQL_ACTIVE_ENVIRONMENTS => 116 # 116 > + , SQL_ALTER_DOMAIN => 117 # 117 > + , SQL_SQL_CONFORMANCE => 118 # 118 > + , SQL_DATETIME_LITERALS => 119 # 119 > + , SQL_BATCH_ROW_COUNT => 120 # 120 > + , SQL_BATCH_SUPPORT => 121 # 121 > + , SQL_CONVERT_WCHAR => 122 # 122 > + , SQL_CONVERT_INTERVAL_DAY_TIME => 123 # 123 > + , SQL_CONVERT_INTERVAL_YEAR_MONTH => 124 # 124 > + , SQL_CONVERT_WLONGVARCHAR => 125 # 125 > + , SQL_CONVERT_WVARCHAR => 126 # 126 > + , SQL_CREATE_ASSERTION => 127 # 127 > + , SQL_CREATE_CHARACTER_SET => 128 # 128 > + , SQL_CREATE_COLLATION => 129 # 129 > + , SQL_CREATE_DOMAIN => 130 # 130 > + , SQL_CREATE_SCHEMA => 131 # 131 > + , SQL_CREATE_TABLE => 132 # 132 > + , SQL_CREATE_TRANSLATION => 133 # 133 > + , SQL_CREATE_VIEW => 134 # 134 > + , SQL_DRIVER_HDESC => 135 # 135 > + , SQL_DROP_ASSERTION => 136 # 136 > + , SQL_DROP_CHARACTER_SET => 137 # 137 > + , SQL_DROP_COLLATION => 138 # 138 > + , SQL_DROP_DOMAIN => 139 # 139 > + , SQL_DROP_SCHEMA => 140 # 140 > + , SQL_DROP_TABLE => 141 # 141 > + , SQL_DROP_TRANSLATION => 142 # 142 > + , SQL_DROP_VIEW => 143 # 143 > + , SQL_DYNAMIC_CURSOR_ATTRIBUTES1 => 144 # 144 > + , SQL_DYNAMIC_CURSOR_ATTRIBUTES2 => 145 # 145 > + , SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 => 146 # 146 > + , SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2 => 147 # 147 > + , SQL_INDEX_KEYWORDS => 148 # 148 > + , SQL_INFO_SCHEMA_VIEWS => 149 # 149 > + , SQL_KEYSET_CURSOR_ATTRIBUTES1 => 150 # 150 > + , SQL_KEYSET_CURSOR_ATTRIBUTES2 => 151 # 151 > + , SQL_ODBC_INTERFACE_CONFORMANCE => 152 # 152 > + , SQL_PARAM_ARRAY_ROW_COUNTS => 153 # 153 > + , SQL_PARAM_ARRAY_SELECTS => 154 # 154 > + , SQL_SQL92_DATETIME_FUNCTIONS => 155 # 155 > + , SQL_SQL92_FOREIGN_KEY_DELETE_RULE => 156 # 156 > + , SQL_SQL92_FOREIGN_KEY_UPDATE_RULE => 157 # 157 > + , SQL_SQL92_GRANT => 158 # 158 > + , SQL_SQL92_NUMERIC_VALUE_FUNCTIONS => 159 # 159 > + , SQL_SQL92_PREDICATES => 160 # 160 > + , SQL_SQL92_RELATIONAL_JOIN_OPERATORS => 161 # 161 > + , SQL_SQL92_REVOKE => 162 # 162 > + , SQL_SQL92_ROW_VALUE_CONSTRUCTOR => 163 # 163 > + , SQL_SQL92_STRING_FUNCTIONS => 164 # 164 > + , SQL_SQL92_VALUE_EXPRESSIONS => 165 # 165 > + , SQL_STANDARD_CLI_CONFORMANCE => 166 # 166 > + , SQL_STATIC_CURSOR_ATTRIBUTES1 => 167 # 167 > + , SQL_STATIC_CURSOR_ATTRIBUTES2 => 168 # 168 > + , SQL_AGGREGATE_FUNCTIONS => 169 # 169 > + , SQL_DDL_INDEX => 170 # 170 > + , SQL_DM_VER => 171 # 171 > + , SQL_INSERT_STATEMENT => 172 # 172 > + , SQL_CONVERT_GUID => 173 # 173 > + , SQL_INFO_DRIVER_START => 1000 # 1000 > + , SQL_XOPEN_CLI_YEAR => 10000 # 10000 > + , SQL_CURSOR_SENSITIVITY => 10001 # 10001 10001 > + , SQL_DESCRIBE_PARAMETER => 10002 # 10002 10002 > + , SQL_CATALOG_NAME => 10003 # 10003 10003 > + , SQL_COLLATING_SEQUENCE => 10004 # 10004 > + , SQL_COLLATION_SEQ => 10004 # 10004 > + , SQL_MAXIMUM_IDENTIFIER_LENGTH => 10005 # 10005 10005 > + , SQL_MAX_IDENTIFIER_LEN => 10005 # 10005 > + , SQL_ASYNC_MODE => 10021 # 10021 > + , SQL_MAX_ASYNC_CONCURRENT_STATEMENTS => 10022 # 10022 > + , SQL_MAXIMUM_STMT_OCTETS => 20000 # 20000 > + , SQL_MAXIMUM_STMT_OCTETS_DATA => 20001 # 20001 > + , SQL_MAXIMUM_STMT_OCTETS_SCHEMA => 20002 # 20002 > + , SQL_OJ_CAPABILITIES => 65003 # 65003 > + ); > + > + 1; > diff -Nrc DBI-1.20.orig/t/getinfo.t DBI-1.20/t/getinfo.t > *** DBI-1.20.orig/t/getinfo.t Thu Jan 01 01:00:00 1970 > --- DBI-1.20/t/getinfo.t Wed Nov 28 11:08:48 2001 > *************** > *** 0 **** > --- 1,58 ---- > + > + $| = 1; > + > + use strict; > + > + use Test::More tests => 7; > + > + BEGIN { use_ok('DBI') } > + > + my $dbh; > + > + # ----------------------------------------------------------------------------- > + { > + $dbh = DBI->connect('dbi:NullP:') or die $DBI::errstr; > + $dbh->{ RaiseError } = 1; > + $dbh->{ PrintError } = 1; > + > + ok( defined $dbh,'Database handle defined'); > + > + ok( $DBD::NullP::VERSION,'$DBD::NullP::VERSION'); > + > + is( $dbh->{ RaiseError }, 1,'$dbh->{ RaiseError }'); > + } > + # ----------------------------------------------------------------------------- > + { > + no strict 'subs'; > + > + eval { my $v = $dbh->{ SQL_XXX }; }; > + like( $@, qr/unrecognised attribute/ > + ,'unrecognised attribute'); > + > + # $dbh->trace( 9 ); > + is( $dbh->{ SQL_DBMS_VER },'GetInfo: SQL_DBMS_VER' > + ,'Fetch: $dbh->{ SQL_DBMS_VER }'); > + # $dbh->trace( 0 ); > + > + is( $dbh->get_info( SQL_DBMS_NAME ),'GetInfo: SQL_DBMS_NAME' > + ,'Call: $dbh->get_info( SQL_DBMS_NAME )'); > + > + } > + # ----------------------------------------------------------------------------- > + __END__ > + > + # ----------------------------------------------------------------------------- > + { > + local $\ = "\n"; > + use DBI::Const(); > + use Benchmark(); > + my $t0 = new Benchmark; > + while ( my ( $k, $v ) = each %DBI::Const::GetInfo ) > + { # x86 200 MHz 64Mb > + # $dbh->get_info( $k ); # 0 wallclock secs ( 0.04 usr + >0.00 sys = 0.04 CPU) > + # print $k, ' => ', $dbh->get_info( $k ); # 0 wallclock secs ( 0.09 usr + >0.06 sys = 0.15 CPU) > + # $dbh->{ $k }; # 0 wallclock secs ( 0.10 usr + >0.00 sys = 0.10 CPU) > + # print $k, ' => ', $dbh->{ $k }; # 0 wallclock secs ( 0.14 usr + >0.07 sys = 0.21 CPU) > + } > + print Benchmark::timestr( Benchmark::timediff( Benchmark->new, $t0 ) ); > + }