Mercurial > hg > monetdb-perl
view MonetDB-CLI-MapiPP/MonetDB/CLI/MapiPP.pm @ 12:8c8bd15f7a0b
Updated copyright year.
author | Sjoerd Mullender <sjoerd@acm.org> |
---|---|
date | Mon, 30 Sep 2019 21:27:37 +0200 (2019-09-30) |
parents | b9e0744b2396 |
children | 1bdbb3ca1ae0 |
line wrap: on
line source
package MonetDB::CLI::MapiPP; use Text::ParseWords(); use Encode (); use MonetDB::CLI::Mapi; use strict; use warnings; our $VERSION = '1.00'; my %unescape = ( n => "\n", t => "\t", r => "\r", f => "\f"); sub unquote { if (!defined($_) || $_ eq 'NULL' || $_ eq 'nil') { $_ = undef; return; } if ( /^["']/) { s/^["']//; s/["']$//; s/\\([0-7]{3}|.)/length($1) == 3 ? chr(oct($1)) : ($unescape{$1} || $1)/eg; } } sub connect { my ($class, $host, $port, $user, $pass, $lang, $db) = @_; my $h = new MonetDB::CLI::Mapi($host, $port, $user, $pass, $lang, $db, 0) or die "Making connection failed: $@"; bless { h => $h },'MonetDB::CLI::MapiPP::Cxn'; } package MonetDB::CLI::MapiPP::Cxn; sub query { my ($self, $statement) = @_; my $h = $self->new_handle; $h->query($statement); return $h; } sub new_handle { my ($self) = @_; bless { h => $self->{h} },'MonetDB::CLI::MapiPP::Req'; } sub DESTROY { my ($self) = @_; $self->{h}->disconnect(); return; } package MonetDB::CLI::MapiPP::Req; sub query { my ($self, $statement) = @_; my $h = $self->{h}; $h->doRequest($statement); $self->{i} = -1; $self->{rows} = []; $self->{querytype} = -1; $self->{id} = -1; $self->{affrows} = -1; $self->{colcnt} = -1; $self->{colnames} = []; $self->{coltypes} = []; $self->{collens} = []; my $tpe = $h->getReply(); if ($tpe > 0) { # "regular" resultset, or just "tuple" $self->{querytype} = 1; $self->{id} = $h->{id} || -1; $self->{affrows} = $h->{count} if $h->{count}; $self->{colcnt} = $h->{nrcols} if $h->{nrcols}; my $hdr; foreach $hdr (@{$h->{hdrs}}) { my $nme = substr($hdr, rindex($hdr, "# ")); $hdr = substr($hdr, 2, -(length($nme) + 1)); if ($nme eq "# name") { @{$self->{colnames}} = split(/,\t/, $hdr); } elsif ($nme eq "# type") { @{$self->{coltypes}} = split(/,\t/, $hdr); } elsif ($nme eq "# length") { @{$self->{collens}} = split(/,\t/, $hdr); } # TODO: table_name } # we must pre-fetch if this is not an SQL result-set if (!defined $h->{count}) { do { utf8::decode($self->{h}->{row}); my @cols = split(/,\t */, $h->{row}); my $i = -1; for (@cols) { s/^\[ //; s/[ \t]+\]$//; MonetDB::CLI::MapiPP::unquote(); } push(@{$self->{rows}}, [@cols]); } while (($tpe = $h->getReply()) > 0); $self->{affrows} = @{$self->{rows}}; undef $self->{id}; } } elsif ($tpe == -1) { # error die $h->{errstr}; } elsif ($tpe == -2) { # update count/affected rows $self->{affrows} = $h->{count}; } } sub querytype { my ($self) = @_; return $self->{querytype}; } sub id { my ($self) = @_; return $self->{id} || -1; } sub rows_affected { my ($self) = @_; return $self->{affrows}; } sub columncount { my ($self) = @_; return $self->{colcnt}; } sub name { my ($self, $fnr) = @_; return $self->{colnames}[$fnr] || ''; } sub type { my ($self, $fnr) = @_; return $self->{coltypes}[$fnr] || ''; } sub length { my ($self, $fnr) = @_; return $self->{collens}[$fnr] || 0; } sub fetch { my ($self) = @_; return if ++$self->{i} >= $self->{affrows}; if ($self->{id}) { utf8::decode($self->{h}->{row}); my @cols = split(/,\t */, $self->{h}->{row}); my $i = -1; $cols[0] =~ s/^\[ //; $cols[-1] =~ s/[ \t]+\]$//; for (@cols) { MonetDB::CLI::MapiPP::unquote(); } $self->{currow} = [@cols]; $self->{h}->getReply(); } else { $self->{currow} = $self->{rows}[$self->{i}]; } return @{$self->{currow}}; } sub field { my ($self, $fnr) = @_; return $self->{currow}[$fnr]; } sub finish { my ($self) = @_; $self->{$_} = -1 for qw(querytype id tuplecount columncount i); $self->{$_} = "" for qw(query); $self->{$_} = [] for qw(rows name type length); return; } sub DESTROY { my ($self) = @_; return; } __PACKAGE__; =head1 NAME MonetDB::CLI::MapiPP - MonetDB::CLI implementation, using the Mapi protocol =head1 DESCRIPTION MonetDB::CLI::MapiPP is an implementation of the MonetDB call level interface L<MonetDB::CLI>. It's a Pure Perl module. It uses the Mapi protocol - a text based communication layer on top of TCP. Normally, you don't use this module directly, but let L<MonetDB::CLI> choose an implementation module. =head1 AUTHORS Steffen Goeldner E<lt>sgoeldner@cpan.orgE<gt>. Fabian Groffen E<lt>fabian@cwi.nlE<gt>. =head1 COPYRIGHT AND LICENCE This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. =head1 SEE ALSO =head2 MonetDB Homepage : https://www.monetdb.org/ =head2 Perl modules L<MonetDB::CLI> =cut # vim: set ts=2 sw=2 expandtab: