Cassandra-Client
view release on metacpan or search on metacpan
lib/Cassandra/Client/Protocol.pm view on Meta::CPAN
package Cassandra::Client::Protocol;
our $AUTHORITY = 'cpan:TVDW';
$Cassandra::Client::Protocol::VERSION = '0.21';
use 5.010;
use strict;
use warnings;
use Encode;
require Exporter;
our @ISA= qw(Exporter);
use Cassandra::Client::Error::Base;
use Cassandra::Client::Error::ReadTimeoutException;
use Cassandra::Client::Error::WriteTimeoutException;
use Cassandra::Client::Error::UnavailableException;
use constant BIGINT_SUPPORTED => eval { unpack('q>', "\0\0\0\0\0\0\0\1") };
use if !BIGINT_SUPPORTED, 'Math::BigInt';
our (@EXPORT_OK, %EXPORT_TAGS);
our (%consistency_lookup, %batch_type_lookup);
BEGIN {
my %constants= (
OPCODE_ERROR => 0,
OPCODE_STARTUP => 1,
OPCODE_READY => 2,
OPCODE_AUTHENTICATE => 3,
OPCODE_OPTIONS => 5,
OPCODE_SUPPORTED => 6,
OPCODE_QUERY => 7,
OPCODE_RESULT => 8,
OPCODE_PREPARE => 9,
OPCODE_EXECUTE => 10,
OPCODE_REGISTER => 11,
OPCODE_EVENT => 12,
OPCODE_BATCH => 13,
OPCODE_AUTH_CHALLENGE => 14,
OPCODE_AUTH_RESPONSE => 15,
OPCODE_AUTH_SUCCESS => 16,
RESULT_VOID => 1,
RESULT_ROWS => 2,
RESULT_SET_KEYSPACE => 3,
RESULT_PREPARED => 4,
RESULT_SCHEMA_CHANGE => 5,
CONSISTENCY_ANY => 0,
CONSISTENCY_ONE => 1,
CONSISTENCY_TWO => 2,
CONSISTENCY_THREE => 3,
CONSISTENCY_QUORUM => 4,
CONSISTENCY_ALL => 5,
CONSISTENCY_LOCAL_QUORUM => 6,
CONSISTENCY_EACH_QUORUM => 7,
CONSISTENCY_SERIAL => 8,
CONSISTENCY_LOCAL_SERIAL => 9,
CONSISTENCY_LOCAL_ONE => 10,
TYPE_CUSTOM => 0x00,
TYPE_ASCII => 0x01,
TYPE_BIGINT => 0x02,
TYPE_BLOB => 0x03,
TYPE_BOOLEAN => 0x04,
TYPE_COUNTER => 0x05,
TYPE_DECIMAL => 0x06,
TYPE_DOUBLE => 0x07,
TYPE_FLOAT => 0x08,
TYPE_INT => 0x09,
TYPE_TEXT => 0x0A, # deprecated/removed
TYPE_TIMESTAMP => 0x0B,
TYPE_UUID => 0x0C,
TYPE_VARCHAR => 0x0D,
TYPE_VARINT => 0x0E,
TYPE_TIMEUUID => 0x0F,
lib/Cassandra/Client/Protocol.pm view on Meta::CPAN
my $paging_state= $metadata->{paging_state};
my $flags= ($columns ? 0 : 4) | (defined($paging_state) ? 2 : 0);
my $out= pack_int($flags);
$out .= pack_int($columns ? (0+@$columns) : 0);
$out .= pack_bytes($paging_state) if $flags & 2;
unless ($flags & 4) {
for my $column (@$columns) {
$out .= pack_string($column->[0]).pack_string($column->[1]);
$out .= pack_string($column->[2]).pack_option_type($column->[3]);
}
}
return $out;
}
# Query parameters
sub pack_queryparameters {
my ($consistency, $skip_metadata, $page_size, $paging_state, $timestamp, $row)= @_;
my $has_row= defined($row) && length($row);
my $flags= (
0
| (($has_row && 0x01) || 0)
| (($skip_metadata && 0x02) || 0)
| (($page_size && 0x04) || 0)
| (($paging_state && 0x08) || 0)
| (($timestamp && 0x20) || 0)
);
return (
pack('nC', $consistency, $flags)
. ($row || '')
. ($page_size ? pack('l>', $page_size) : '')
. ($paging_state ? pack('l>/a', $paging_state) : '')
. ($timestamp ? (BIGINT_SUPPORTED ? pack('q>', $timestamp) : bigint_to_bytes($timestamp)) : '')
);
}
sub unpack_errordata {
my $code= &unpack_int;
my %error;
$error{code}= $code;
$error{message}= &unpack_string;
$error{is_timeout}= ( $code == 0x1001 || $code == 0x1100 || $code == 0x1200 );
if ($code == 0x1000) {
# Unavailable
$error{cl}= &unpack_short;
$error{required}= &unpack_int;
$error{alive}= &unpack_int;
return Cassandra::Client::Error::UnavailableException->new(%error);
} elsif ($code == 0x1100) {
# Write timeout
$error{cl}= &unpack_short;
$error{received}= &unpack_int;
$error{blockfor}= &unpack_int;
$error{write_type}= &unpack_string;
return Cassandra::Client::Error::WriteTimeoutException->new(%error);
} elsif ($code == 0x1200) {
# Read timeout
$error{cl}= &unpack_short;
$error{received}= &unpack_int;
$error{blockfor}= &unpack_int;
$error{data_present}= &unpack_char;
return Cassandra::Client::Error::ReadTimeoutException->new(%error);
}
return Cassandra::Client::Error::Base->new(%error);
}
# Support for 32bit perl
sub bigint_to_bytes {
my $mb= Math::BigInt->new($_[0]);
if ($_[0] !~ /^-?[0-9\.E]+$/i) { # Idk, approximate it
warn "Argument $_[0] isn't numeric";
}
my $negative= $mb->is_neg && $mb != 0;
if ($negative) {
$mb *= -1; # Flips the bits, adds one
$mb -= 1; # Removes that one
}
my $hex= $mb->as_hex;
$hex =~ s/^0x//;
my $bytes= pack('H*', substr(("0"x16).$hex, -16));
if ($negative) {
$bytes= ~$bytes; # Flip those bits back
}
return $bytes;
}
1;
__END__
=pod
=head1 NAME
Cassandra::Client::Protocol
=head1 VERSION
version 0.21
=head1 AUTHOR
Tom van der Woerdt <tvdw@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2023 by Tom van der Woerdt.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
( run in 3.121 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )