Steffen Goeldner wrote:
> 
> Next, I'll try to find proper TYPE_NAME's. I think about restricting
> SchemaProviderTypes by $AdoType, $IsLong, $IsFixed. This gives:
> 
>  1)  0 records, if the provider is buggy
>  2)  1 record in most cases
>  3) >1 records, e.g. for different max column sizes
> 
> Case 2) is trivial.
> Case 1) may return NULL (undef) or an standard SQL name?
> Case 3) should return the first type which has a large enough
>         COLUMN_SIZE
> 

For your demo table, column_info() returns:

||demo|   ID|  4|      Long| 10|   | ||0||         |  4| |   | 1| NO
||demo| num1|  4|      Long| 10|   | ||1||        0|  4| |   | 2|YES
||demo| num2|  5|     Short|  5|   | ||1||        0|  5| |   | 3|YES
||demo| num3|  6|    Single|  7|   | ||1||        0|  6| |   | 4|YES
||demo| num4|  8|    Double| 15|   | ||1||        0|  8| |   | 5|YES
||demo| num5|-11|      GUID|   |   | ||1||         |-11| |   | 6|YES
||demo| num6|  2|   Decimal| 18|   |0||1||        0|  2| |   | 7|YES
||demo| txt1| -9|   VarChar| 50|100| ||1||         | -9| |100| 8|YES
||demo| txt2| -9|   VarChar|255|510| ||1||         | -9| |510| 9|YES
||demo|memo1|-10|  LongText|  0|  0| ||1||         |-10| |  0|10|YES
||demo|  dt1| 93|  DateTime|   |   | ||1||         |  9|3|   |11|YES
||demo| cur1|  2|  Currency| 19|   | ||1||        0|  2| |   |12|YES
||demo| cur2|  2|  Currency| 19|   | ||1||        0|  2| |   |13|YES
||demo| cur3|  2|  Currency| 19|   | ||1||        0|  2| |   |14|YES
||demo| cur4|  2|  Currency| 19|   | ||1||        0|  2| |   |15|YES
||demo| cur5|  2|  Currency| 19|   | ||1||        0|  2| |   |16|YES
||demo| cur6|  2|  Currency| 19|   | ||1||        0|  2| |   |17|YES
||demo| cur7|  2|  Currency| 19|   | ||1||        0|  2| |   |18|YES
||demo|  an2|-11|      GUID|   |   | ||1||GenGUID()|-11| |   |19|YES
||demo|  yn1| 16|       Bit|  2|   | ||0||         | 16| |   |20| NO
||demo|  yn2| 16|       Bit|  2|   | ||0||         | 16| |   |21| NO
||demo|  yn3| 16|       Bit|  2|   | ||0||         | 16| |   |22| NO
||demo|  oo1| -4|LongBinary|  0|  0| ||1||         | -4| |  0|23|YES
||demo|  hl1|-10|  LongText|  0|  0| ||1||         |-10| |  0|24|YES

And for this table:

create table demo3
(
  cShort      Short
, cLong       Long
, cSingle     Single
, cDouble     Double
, cCurrency   Currency
, cDateTime   DateTime
, cBit        Bit
, cByte       Byte
, cGUID       GUID
, cBigBinary  BigBinary
, cLongBinary LongBinary
, cVarBinary  VarBinary (20)
, cLongText   LongText
, cVarChar    VarChar   (10)
, cDecimal    Decimal   (11,2)
)

column_info() returns:

||demo3|     cShort|  5|     Short|   5|    | ||1|||  5| |    | 1|YES
||demo3|      cLong|  4|      Long|  10|    | ||1|||  4| |    | 2|YES
||demo3|    cSingle|  6|    Single|   7|    | ||1|||  6| |    | 3|YES
||demo3|    cDouble|  8|    Double|  15|    | ||1|||  8| |    | 4|YES
||demo3|  cCurrency|  2|  Currency|  19|    | ||1|||  2| |    | 5|YES
||demo3|  cDateTime| 93|  DateTime|    |    | ||1|||  9|3|    | 6|YES
||demo3|       cBit| 16|       Bit|   2|    | ||0||| 16| |    | 7| NO
||demo3|      cByte|  0|      Byte|   3|    | ||1|||  0| |    | 8|YES
||demo3|      cGUID|-11|      GUID|    |    | ||1|||-11| |    | 9|YES
||demo3| cBigBinary| -3| BigBinary|4000|4000| ||1||| -3| |4000|10|YES
||demo3|cLongBinary| -4|LongBinary|   0|   0| ||1||| -4| |   0|11|YES
||demo3| cVarBinary| -3| VarBinary|  20|  20| ||1||| -3| |  20|12|YES
||demo3|  cLongText|-10|  LongText|   0|   0| ||1|||-10| |   0|13|YES
||demo3|   cVarChar| -9|   VarChar|  10|  20| ||1||| -9| |  20|14|YES
||demo3|   cDecimal|  2|   Decimal|  11|    |2||1|||  2| |    |15|YES


Steffen
*** F:\tmp\DBD-ADO\lib\DBD\ADO.pm       Mon Nov 26 21:48:40 2001
--- W:\info\lang\perl\test\DBI\DBD\ADO.pm       Sat Dec 08 21:55:57 2001
***************
*** 95,100 ****
--- 95,101 ----
  my %connect_options;
  
  my $myado_types_supported = ();
+ my $myado_types_supported2 = ();
  
  
  
***************
*** 114,121 ****
        use constant DBPROPVAL_TC_NONE  => 0;
  
        use constant SQL_GUID                                                          
                                         => -11;
!       use constant SQL_BIGINT                                                        
                                 => - 6;
        use constant SQL_UNKNOWN_TYPE                                                  
                 =>   0;
        use constant SQL_BIT                          =>   14;
        use constant SQL_BIT_VARYING                  =>   15;
        use constant SQL_BOOLEAN                      =>   16;
--- 115,132 ----
        use constant DBPROPVAL_TC_NONE  => 0;
  
        use constant SQL_GUID                         =>  -11;
!       use constant SQL_WLONGVARCHAR                 =>  -10;
!       use constant SQL_WVARCHAR                     =>   -9;
!       use constant SQL_WCHAR                        =>   -8;
!       use constant SQL_BIT                          =>   -7;
!       use constant SQL_TINYINT                      =>   -6;
!       use constant SQL_BIGINT                       =>   -5;
!       use constant SQL_LONGVARBINARY                =>   -4;
!       use constant SQL_VARBINARY                    =>   -3;
!       use constant SQL_BINARY                       =>   -2;
!       use constant SQL_LONGVARCHAR                  =>   -1;
        use constant SQL_UNKNOWN_TYPE                 =>    0;
+ 
        use constant SQL_BIT                          =>   14;
        use constant SQL_BIT_VARYING                  =>   15;
        use constant SQL_BOOLEAN                      =>   16;
***************
*** 162,167 ****
--- 173,198 ----
            $VT_I4_BYREF = Win32::OLE::Variant::VT_I4()
                         | Win32::OLE::Variant::VT_BYREF();
  
+ 
+       $myado_types_supported2 = {
+                     # AdoType     IsLong IsFixed => SqlType
+         $ado_consts->{adBinary   } => { 0 => { 0 =>      SQL_VARBINARY
+                                              , 1 =>      SQL_BINARY        }
+                                       , 1 => { 0 =>      SQL_LONGVARBINARY
+                                              , 1 =>      SQL_UNKNOWN_TYPE  }}
+       , $ado_consts->{adChar     } => { 0 => { 0 => DBI::SQL_VARCHAR
+                                              , 1 => DBI::SQL_CHAR          }
+                                       , 1 => { 0 =>      SQL_LONGVARCHAR
+                                              , 1 =>      SQL_UNKNOWN_TYPE  }}
+       , $ado_consts->{adWChar    } => { 0 => { 0 =>      SQL_WVARCHAR
+                                              , 1 =>      SQL_WCHAR         }
+                                       , 1 => { 0 =>      SQL_WLONGVARCHAR
+                                              , 1 =>      SQL_UNKNOWN_TYPE  }}
+ #     , $ado_consts->{adVarBinary} =>
+ #     , $ado_consts->{adVarChar  } =>
+ #     , $ado_consts->{adVarWChar } =>
+       };
+ 
        $myado_types_supported = {
          $ado_consts->{adArray}                                                =>     
 SQL_ARRAY
        , $ado_consts->{adBigInt}                                               =>     
 SQL_BIGINT
***************
*** 171,180 ****
        , $ado_consts->{adChapter}                                      =>      
SQL_UNKNOWN_TYPE
        , $ado_consts->{adChar}                                                 => 
DBI::SQL_CHAR
        , $ado_consts->{adCurrency}                                     => 
DBI::SQL_NUMERIC
!       , $ado_consts->{adDate}                                                 => 
DBI::SQL_DATE
!       , $ado_consts->{adDBDate}                                               => 
DBI::SQL_DATE
!       , $ado_consts->{adDBTime}                                               => 
DBI::SQL_TIME
!       , $ado_consts->{adDBTimeStamp}                  => DBI::SQL_TIMESTAMP
        , $ado_consts->{adDecimal}                                      => 
DBI::SQL_DECIMAL
        , $ado_consts->{adDouble}                                               => 
DBI::SQL_DOUBLE
        , $ado_consts->{adEmpty}                                                =>     
 SQL_UNKNOWN_TYPE
--- 202,211 ----
        , $ado_consts->{adChapter}                                      =>      
SQL_UNKNOWN_TYPE
        , $ado_consts->{adChar}                                                 => 
DBI::SQL_CHAR
        , $ado_consts->{adCurrency}                                     => 
DBI::SQL_NUMERIC
!       , $ado_consts->{adDate}                                                 =>     
 SQL_TYPE_TIMESTAMP # XXX Not really!
!       , $ado_consts->{adDBDate}                                               =>     
 SQL_TYPE_DATE
!       , $ado_consts->{adDBTime}                                               =>     
 SQL_TYPE_TIME
!       , $ado_consts->{adDBTimeStamp}                  =>      SQL_TYPE_TIMESTAMP
        , $ado_consts->{adDecimal}                                      => 
DBI::SQL_DECIMAL
        , $ado_consts->{adDouble}                                               => 
DBI::SQL_DOUBLE
        , $ado_consts->{adEmpty}                                                =>     
 SQL_UNKNOWN_TYPE
***************
*** 754,759 ****
--- 785,862 ----
                $sth;
        }
  
+       sub column_info {
+               my( $dbh, @Criteria ) = @_;
+               my $Criteria = \@Criteria if @Criteria;
+               my $QueryType = 'adSchemaColumns';
+               my @Rows;
+               my $conn = $dbh->{ado_conn};
+               my $tmpCursorLocation = $conn->{CursorLocation};
+               $conn->{CursorLocation} = $ado_consts->{adUseClient};
+ 
+               my $RecSet = $conn->OpenSchema( $ado_consts->{$QueryType}, $Criteria );
+               my $lastError = DBD::ADO::errors($conn);
+               return DBI::set_err($dbh, $DBD::ADO::err,
+                       "Error occurred with call to OpenSchema ($QueryType): 
+$lastError")
+                               if $lastError;
+ 
+               $RecSet->{Sort} = 'TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, 
+ORDINAL_POSITION';
+               $lastError = DBD::ADO::errors($conn);
+               return DBI::set_err($dbh, $DBD::ADO::err,
+                       "Error occurred defining sort order : $lastError")
+                               if $lastError;
+ 
+               while ( ! $RecSet->{EOF} ) {
+                       my @Fields;
+                       my $AdoType    = $RecSet->Fields('DATA_TYPE'   )->{Value};
+                       my $ColFlags   = $RecSet->Fields('COLUMN_FLAGS')->{Value};
+                       my $IsLong     = ( $ColFlags & $ado_consts->{adFldLong } ) ? 1 
+: 0;
+                       my $IsFixed    = ( $ColFlags & $ado_consts->{adFldFixed} ) ? 1 
+: 0;
+                       my @SqlType    = DBD::ADO::db::convert_ado_to_odbc( $dbh, 
+$AdoType, $IsFixed, $IsLong );
+ #                     my $TypeInfo   = $dbh->type_info( $SqlType[0] );
+ #                     my $TypeName   = $TypeInfo ? $TypeInfo->{TYPE_NAME} : undef;
+                       my $TypeName;
+                       my $IsNullable = $RecSet->Fields('IS_NULLABLE')->{Value} ? 
+'YES' : 'NO';
+                       my $ColSize    = $RecSet->Fields('NUMERIC_PRECISION'       
+)->{Value}
+                                     || 
+$RecSet->Fields('CHARACTER_MAXIMUM_LENGTH')->{Value};
+                       my $ado_tis    = DBD::ADO::db::_ado_get_type_info_for( $dbh, 
+$AdoType, $IsFixed, $IsLong );
+ #                     print '***', $AdoType, $IsFixed, $IsLong, ' => ', $ColSize, 
+$RecSet->Fields('COLUMN_NAME')->{Value};
+                       for my $ti ( sort { $a->{COLUMN_SIZE} <=> $b->{COLUMN_SIZE} } 
+@$ado_tis )
+                       {
+                               $TypeName = $ti->{TYPE_NAME};
+ #                             print '***', $AdoType, $IsFixed, $IsLong, ' => ', 
+$ti->{TYPE_NAME}, $ti->{COLUMN_SIZE}, $ColSize, 
+$RecSet->Fields('COLUMN_NAME')->{Value};
+                               last if $ti->{COLUMN_SIZE} >= $ColSize;
+                       }
+                       $Fields[ 0] = $RecSet->Fields('TABLE_CATALOG'           
+)->{Value}; # TABLE_CAT
+                       $Fields[ 1] = $RecSet->Fields('TABLE_SCHEMA'            
+)->{Value}; # TABLE_SCHEM
+                       $Fields[ 2] = $RecSet->Fields('TABLE_NAME'              
+)->{Value}; # TABLE_NAME
+                       $Fields[ 3] = $RecSet->Fields('COLUMN_NAME'             
+)->{Value}; # COLUMN_NAME
+                       $Fields[ 4] = $SqlType[0]                                      
+   ; # DATA_TYPE !!!
+                       $Fields[ 5] = $TypeName                                        
+   ; # TYPE_NAME !!!
+                       $Fields[ 6] = $ColSize                                         
+   ; # COLUMN_SIZE !!! MAX for *LONG*
+                       $Fields[ 7] = $RecSet->Fields('CHARACTER_OCTET_LENGTH'  
+)->{Value}; # BUFFER_LENGTH !!! MAX for *LONG*, ... (e.g. num)
+                       $Fields[ 8] = $RecSet->Fields('NUMERIC_SCALE'           
+)->{Value}; # DECIMAL_DIGITS ???
+                       $Fields[ 9] = undef                                            
+   ; # NUM_PREC_RADIX !!!
+                       $Fields[10] = $RecSet->Fields('IS_NULLABLE'             
+)->{Value}; # NULLABLE !!!
+                       $Fields[11] = $RecSet->Fields('DESCRIPTION'             
+)->{Value}; # REMARKS
+                       $Fields[12] = $RecSet->Fields('COLUMN_DEFAULT'          
+)->{Value}; # COLUMN_DEF
+                       $Fields[13] = $SqlType[1]                                      
+   ; # SQL_DATA_TYPE !!!
+                       $Fields[14] = $SqlType[2]                                      
+   ; # SQL_DATETIME_SUB !!!
+                       $Fields[15] = $RecSet->Fields('CHARACTER_OCTET_LENGTH'  
+)->{Value}; # CHAR_OCTET_LENGTH !!! MAX for *LONG*
+                       $Fields[16] = $RecSet->Fields('ORDINAL_POSITION'        
+)->{Value}; # ORDINAL_POSITION
+                       $Fields[17] = $IsNullable                                      
+   ; # IS_NULLABLE !!!
+ 
+                       push( @Rows, \@Fields );
+                       $RecSet->MoveNext;
+               }
+               $RecSet->Close; undef $RecSet;
+               $conn->{CursorLocation} = $tmpCursorLocation;
+ 
+               DBI->connect('dbi:Sponge:','','', { RaiseError => 1 })->prepare(
+                       $QueryType, { rows => \@Rows, NAME =>
+                       [ qw( TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME DATA_TYPE 
+TYPE_NAME COLUMN_SIZE BUFFER_LENGTH DECIMAL_DIGITS NUM_PREC_RADIX NULLABLE REMARKS 
+COLUMN_DEF SQL_DATA_TYPE SQL_DATETIME_SUB CHAR_OCTET_LENGTH ORDINAL_POSITION 
+IS_NULLABLE ) ]});
+       }
+ 
        sub primary_key_info {
                my( $dbh, @Criteria ) = @_;
                my $QueryType = 'adSchemaPrimaryKeys';
***************
*** 1009,1030 ****
                        return \@prov_type_return;
                }
  
        # Attempt to convert an ADO data type into an ODBC/SQL data type.
        sub convert_ado_to_odbc {
!               my ($dbh, $attrib) = @_;
  
                        return $dbh->DBI::set_err( -1,
                                "convert_ado_to_odbc: call without any attributes.")
!                       unless $attrib;
  
                        unless( $ado_types_supported ) {
                                &_determine_type_support($dbh);
                        }
!                       if ( exists $myado_types_supported->{$attrib} ) {
!                               return $myado_types_supported->{$attrib};
                        }
  
!               return $attrib;
        }
  
        sub OpenSchema {
--- 1112,1168 ----
                        return \@prov_type_return;
                }
  
+       sub _ado_get_type_info_for {
+               my ($dbh, $AdoType, $IsFixed, $IsLong ) = @_;
+ 
+               unless( $dbh->{ado_type_info_hash} ) {
+                       my $sth = $dbh->func('adSchemaProviderTypes','OpenSchema');
+                       while ( my $r = $sth->fetchrow_hashref ) {
+                               push 
+@{$dbh->{ado_type_info_hash}{$r->{DATA_TYPE}}{$r->{IS_FIXEDLENGTH}}{$r->{IS_LONG}}}, 
+$r;
+                       }
+               }
+               $dbh->{ado_type_info_hash}{$AdoType}{$IsFixed}{$IsLong} || [];
+       }
+ 
        # Attempt to convert an ADO data type into an ODBC/SQL data type.
        sub convert_ado_to_odbc {
!               my ($dbh, $AdoType, $IsFixed, $IsLong ) = @_;
  
                return $dbh->DBI::set_err( -1,
                        "convert_ado_to_odbc: call without any attributes.")
!                       unless $AdoType;
  
                unless( $ado_types_supported ) {
                        &_determine_type_support($dbh);
                }
! 
!               my $SqlType = 0;
! 
!               if ( $AdoType & $ado_consts->{adArray} ) {
!                       $SqlType = 50;  # XXX DBI::SQL_ARRAY();
!               }
!               elsif ( exists $myado_types_supported2->{$AdoType}{$IsLong}{$IsFixed} 
) {
!                       $SqlType = 
$myado_types_supported2->{$AdoType}{$IsLong}{$IsFixed};
                }
+               elsif ( exists $myado_types_supported->{$AdoType} ) {
+                       $SqlType = $myado_types_supported->{$AdoType};
+               }
+ 
+               if ( wantarray ) {  # DATA_TYPE, SQL_DATA_TYPE, SQL_DATETIME_SUB
+                       my @a = ( $SqlType );
  
!                       if ( 90 < $SqlType && $SqlType < 100 ) {  # SQL_DATETIME
!                               push @a, 9, $SqlType - 90;
!                       }
!                       elsif ( 100 < $SqlType && $SqlType < 120 ) {  # SQL_INTERVAL
!                               push @a, 10, $SqlType - 100;
!                       }
!                       else {
!                               push @a, $SqlType, undef;
!                       }
!                       return @a;
!               }
!               return $SqlType;
        }
  
        sub OpenSchema {

Reply via email to