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 ) ); + }