DBD-Avatica

 view release on metacpan or  search on metacpan

lib/DBD/Avatica/Adapter/Default.pm  view on Meta::CPAN

package DBD::Avatica::Adapter::Default;

use strict;
use warnings;

use Scalar::Util 'weaken';
use Carp 'croak';
use Time::Piece;
use Scalar::Util qw/looks_like_number/;
use DBI ':sql_types';

use Avatica::Client;

#
# JAVA Types https://github.com/JetBrains/jdk8u_jdk/blob/master/src/share/classes/java/sql/Types.java
#

use constant JAVA_TO_REP => {
  -6    => Avatica::Client::Protocol::Rep::BYTE(),                # TINYINT
  5     => Avatica::Client::Protocol::Rep::SHORT(),               # SMALLINT
  4     => Avatica::Client::Protocol::Rep::INTEGER(),             # INTEGER
  -5    => Avatica::Client::Protocol::Rep::LONG(),                # BIGINT
  6     => Avatica::Client::Protocol::Rep::DOUBLE(),              # FLOAT
  8     => Avatica::Client::Protocol::Rep::DOUBLE(),              # DOUBLE
  2     => Avatica::Client::Protocol::Rep::BIG_DECIMAL(),         # NUMERIC
  1     => Avatica::Client::Protocol::Rep::STRING(),              # CHAR
  91    => Avatica::Client::Protocol::Rep::JAVA_SQL_DATE(),       # DATE
  92    => Avatica::Client::Protocol::Rep::JAVA_SQL_TIME(),       # TIME
  93    => Avatica::Client::Protocol::Rep::JAVA_SQL_TIMESTAMP(),  # TIMESTAMP
  -2    => Avatica::Client::Protocol::Rep::BYTE_STRING(),         # BINARY
  -3    => Avatica::Client::Protocol::Rep::BYTE_STRING(),         # VARBINARY
  16    => Avatica::Client::Protocol::Rep::BOOLEAN(),             # BOOLEAN

  -7    => Avatica::Client::Protocol::Rep::BOOLEAN(),             # BIT
  7     => Avatica::Client::Protocol::Rep::DOUBLE(),              # REAL
  3     => Avatica::Client::Protocol::Rep::BIG_DECIMAL(),         # DECIMAL
  12    => Avatica::Client::Protocol::Rep::STRING(),              # VARCHAR
  -1    => Avatica::Client::Protocol::Rep::STRING(),              # LONGVARCHAR
  -4    => Avatica::Client::Protocol::Rep::BYTE_STRING(),         # LONGVARBINARY
  2004  => Avatica::Client::Protocol::Rep::BYTE_STRING(),         # BLOB
  2005  => Avatica::Client::Protocol::Rep::STRING(),              # CLOB
  -15   => Avatica::Client::Protocol::Rep::STRING(),              # NCHAR
  -9    => Avatica::Client::Protocol::Rep::STRING(),              # NVARCHAR
  -16   => Avatica::Client::Protocol::Rep::STRING(),              # LONGNVARCHAR
  2011  => Avatica::Client::Protocol::Rep::STRING(),              # NCLOB
  2009  => Avatica::Client::Protocol::Rep::STRING(),              # SQLXML
  2013  => Avatica::Client::Protocol::Rep::JAVA_SQL_TIME(),       # TIME_WITH_TIMEZONE
  2014  => Avatica::Client::Protocol::Rep::JAVA_SQL_TIMESTAMP(),  # TIMESTAMP_WITH_TIMEZONE

  # Returned by Avatica for Arrays in EMPTY resultsets
  2000  => Avatica::Client::Protocol::Rep::BYTE_STRING(),         # JAVA_OBJECT
};

use constant REP_TO_TYPE_VALUE => {
  Avatica::Client::Protocol::Rep::INTEGER()            => 'number_value',
  Avatica::Client::Protocol::Rep::PRIMITIVE_INT()      => 'number_value',
  Avatica::Client::Protocol::Rep::SHORT()              => 'number_value',
  Avatica::Client::Protocol::Rep::PRIMITIVE_SHORT()    => 'number_value',
  Avatica::Client::Protocol::Rep::LONG()               => 'number_value',
  Avatica::Client::Protocol::Rep::PRIMITIVE_LONG()     => 'number_value',
  Avatica::Client::Protocol::Rep::BYTE()               => 'number_value',
  Avatica::Client::Protocol::Rep::JAVA_SQL_TIME()      => 'number_value',
  Avatica::Client::Protocol::Rep::JAVA_SQL_DATE()      => 'number_value',
  Avatica::Client::Protocol::Rep::JAVA_SQL_TIMESTAMP() => 'number_value',

  Avatica::Client::Protocol::Rep::BYTE_STRING()        => 'bytes_value',

  Avatica::Client::Protocol::Rep::DOUBLE()             => 'double_value',
  Avatica::Client::Protocol::Rep::PRIMITIVE_DOUBLE()   => 'double_value',

  Avatica::Client::Protocol::Rep::PRIMITIVE_CHAR()     => 'string_value',
  Avatica::Client::Protocol::Rep::CHARACTER()          => 'string_value',
  Avatica::Client::Protocol::Rep::BIG_DECIMAL()        => 'string_value',
  Avatica::Client::Protocol::Rep::STRING()             => 'string_value',

  Avatica::Client::Protocol::Rep::BOOLEAN()            => 'bool_value',
  Avatica::Client::Protocol::Rep::PRIMITIVE_BOOLEAN()  => 'bool_value',
};

use constant JAVA_TO_DBI => {
  -6    => SQL_TINYINT,                       # TINYINT
  5     => SQL_SMALLINT,                      # SMALLINT
  4     => SQL_INTEGER,                       # INTEGER
  -5    => SQL_BIGINT,                        # BIGINT
  6     => SQL_FLOAT,                         # FLOAT
  8     => SQL_DOUBLE,                        # DOUBLE
  2     => SQL_NUMERIC,                       # NUMERIC
  1     => SQL_CHAR,                          # CHAR
  91    => SQL_TYPE_DATE,                     # DATE
  92    => SQL_TYPE_TIME,                     # TIME
  93    => SQL_TYPE_TIMESTAMP,                # TIMESTAMP
  -2    => SQL_BINARY,                        # BINARY
  -3    => SQL_VARBINARY,                     # VARBINARY
  16    => SQL_BOOLEAN,                       # BOOLEAN

  -7    => SQL_BIT,                           # BIT
  7     => SQL_REAL,                          # REAL
  3     => SQL_DECIMAL,                       # DECIMAL
  12    => SQL_VARCHAR,                       # VARCHAR
  -1    => SQL_LONGVARCHAR,                   # LONGVARCHAR
  -4    => SQL_LONGVARBINARY,                 # LONGVARBINARY
  2004  => SQL_BLOB,                          # BLOB
  2005  => SQL_CLOB,                          # CLOB
  -15   => SQL_CHAR,                          # NCHAR
  -9    => SQL_VARCHAR,                       # NVARCHAR
  -16   => SQL_LONGVARCHAR,                   # LONGNVARCHAR
  2011  => SQL_CLOB,                          # NCLOB
  2009  => SQL_LONGVARCHAR,                   # SQLXML
  2013  => SQL_TYPE_TIME_WITH_TIMEZONE,       # TIME_WITH_TIMEZONE
  2014  => SQL_TYPE_TIMESTAMP_WITH_TIMEZONE,  # TIMESTAMP_WITH_TIMEZONE

  # Returned by Avatica for Arrays in EMPTY resultsets
  2000  => SQL_ARRAY,                         # JAVA_OBJECT
  2003  => SQL_ARRAY,                         # ARRAY
};

sub new {
  my ($class, %params) = @_;

  my $self = {dbh => $params{dbh}};
  weaken $self->{dbh};

  return bless $self, $class;
}

# params:
# self
# [Avatica::Client::Protocol::ColumnValue, ...]
# [Avatica::Client::Protocol::ColumnMetaData, ...]
sub row_from_jdbc {
  my ($self, $columns_values, $columns_meta) = @_;
  croak 'The number of arguments is not the same as the expected number' if $#{$columns_values} != $#{$columns_meta};
  return [
    map {
        $self->from_jdbc($columns_values->[$_], $columns_meta->[$_])
    }
    0 .. $#{$columns_meta}
  ];
}

# params:
# self
# Avatica::Client::Protocol::ColumnValue
# Avatica::Client::Protocol::ColumnMetaData
sub from_jdbc {
  my ($self, $column_value, $column_meta) = @_;

  my $scalar_value = $column_value->get_scalar_value;

  return (undef,) if $scalar_value && $scalar_value->get_null;

  if ($column_value->get_has_array_value) {
    my $jdbc_type_id = $column_meta->get_type->get_component->get_id;
    my $rep = $self->convert_jdbc_to_rep_type($jdbc_type_id);

    my $type = $self->REP_TO_TYPE_VALUE()->{$rep};
    my $method = "get_$type";

    my $values = [];
    for my $v (@{$column_value->get_array_value_list}) {
      my $res = $v->$method();
      push @$values, $self->convert_from_jdbc($res, $rep);
    }

    return $values;
  }

  my $jdbc_type_id = $column_meta->get_type->get_id;
  my $rep = $self->convert_jdbc_to_rep_type($jdbc_type_id);

  my $type = $self->REP_TO_TYPE_VALUE()->{$rep};
  my $method = "get_$type";

  my $res = $scalar_value->$method();

  return $self->convert_from_jdbc($res, $rep);
}

# params:
# self
# values



( run in 0.713 second using v1.01-cache-2.11-cpan-39bf76dae61 )