DBD-Wire10

 view release on metacpan or  search on metacpan

lib/DBD/Wire10.pm  view on Meta::CPAN

		if ($error) {
			$dbh->DBI::set_err($error->get_error_code || -1, $error->get_error_message, $error->get_error_state);
			return 0;
		} elsif ($@) {
			$dbh->DBI::set_err(-1, $@);
			return 0;
		}
		# Return 1 if connection was reestablished.
		return 1;
	}
	# Return -1 if nothing besides a protocol ping was done.
	return -1;
}

sub disconnect {
	my $dbh = shift;
	my $wire = $dbh->FETCH('wire10_driver_dbh');
	$wire->disconnect if defined $wire;
	$dbh->STORE('wire10_thread_id', undef);
	$dbh->STORE('Active', 0);
	return 1;
}

sub DESTROY {
	my $dbh = shift;
	$dbh->disconnect if $dbh->FETCH('Active');
	$dbh->SUPER::DESTROY;
}

sub last_insert_id {
	my $dbh = shift;
	return $dbh->FETCH('wire10_insertid')
}

# TODO: Support more get_info properties as needed.
sub get_info {
	my $dbh = shift;
	my $type = shift;
	# 17: SQL_DBMS_NAME
	# Difficult to return something intelligent here, the server
	# only reports a version, not a daemon name in the handshake.
	return 'Wire10' if $type == 17;
	# 18: SQL_DBMS_VER
	return $dbh->FETCH('wire10_server_version') if $type == 18;
	# 29: SQL_IDENTIFIER_QUOTE_CHAR
	return '`' if $type == 29;
	# 41: SQL_CATALOG_NAME_SEPARATOR
	return '.' if $type == 41;
	# 114: SQL_CATALOG_LOCATION
	# According to MSDN, 0 means "catalog not supported" which is accurate.
	# (The server happily accepts, discards and prints a catalog named
	#  'def', though.)
	return 0 if $type == 114;
	# Return undef for unknown and unsupported attributes.
	return undef;
}

sub take_imp_data {
	my $dbh = shift;

	# Finish any active statements (important if streaming enabled).
	for my $sth (@{$dbh->{ChildHandles} || []}) {
		next unless $sth;
		$sth->finish if $sth->{Active};
	}

	# Take out core driver and remove reference to it.
	my $wire = $dbh->FETCH('wire10_driver_dbh');
	$dbh->STORE('wire10_driver_dbh', undef);

	# Remove reference to dbh from drh, probably also destroys dbh.
	$dbh->SUPER::take_imp_data;

	# Note: It would be nice to serialize or tie the core such that
	#       it can be be shared among interpreters running in different
	#       processes or threads.  Unfortunately, neither of the available
	#       modules, Storable and threads::shared, seem to be able to
	#       cope with socket handles:
	#
	#       Storable error: "Can't store GLOB items"
	#       threads::shared error: "Invalid value for shared scalar"
	#
	#       For now, we just return the core driver and expect that the
	#       caller serialize and deserialize the object if the caller needs
	#       to use it from a different context.

	# Return the core driver.
	return $wire;
}



package DBD::Wire10::st;

use strict;
use warnings;
use DBI qw(:sql_types);

$DBD::Wire10::st::imp_data_size = 0;

# TODO: Find out if DBI already calls a DBD st constructor somewhere
sub _constructor {
	my $sth = shift;
	my $wire = shift;
	my $sql = shift;

	my $ps = $wire->prepare($sql);

	# Store driver handle and prepared statement for later.
	$sth->STORE('wire10_driver_sth', $wire);
	$sth->STORE('wire10_prepared', $ps);
	$sth->STORE('NUM_OF_PARAMS', $ps->get_marker_count);
}

sub bind_param {
	my $sth = shift;
	my ($index, $value, $attr) = @_;
	my $binary = _test_for_binary_flag($sth, $attr);
	my $ps = $sth->FETCH('wire10_prepared');
	$ps->set_parameter($index, $value, $binary);
	return 1;
}

sub _test_for_binary_flag {
	my $sth = shift;
	my $attr = shift;
	return 0 unless defined $attr;
	my $binary = Net::Wire10::DATA_BINARY;
	my $text = Net::Wire10::DATA_TEXT;
	my $sqltype;
	# May be undefined.
	$sqltype = $attr if ref($attr) eq '';
	$sqltype = $attr->{TYPE} if ref($attr) eq 'HASH';
	if (defined $sqltype) {
		return $binary if $sqltype == SQL_BINARY;
		return $binary if $sqltype == SQL_VARBINARY;
		return $binary if $sqltype == SQL_LONGVARBINARY;
		return $binary if $sqltype == SQL_BLOB;
	}
	# For testing Oracle-based code with MySQL.
	# ORA_BLOB is 113, defined in Oracle.h.
	my $oratype;
	$oratype = $attr->{ora_type} if ref($attr) eq 'HASH';
	return $binary if defined $oratype and $oratype == 113;
	return $text;
}

sub execute {
	my $sth = shift;
	my @new_params = @_;
	my $dbh = $sth->{Database};
	my $wire = $sth->FETCH('wire10_driver_sth');
	my $ps = $sth->FETCH('wire10_prepared');

	unless (defined($ps)) {
		$sth->DBI::set_err(-1, "execute without prepare");
		return undef;
	}

	if (scalar(@new_params) > 0) {
		$ps->clear_parameter;
		my $i = 1;
		foreach my $p (@new_params) {
			$ps->set_parameter($i++, $p, 0);
		}
	}

	my $rowcount = eval {
		$sth->finish;
		my $stream_results = $sth->FETCH('wire10_streaming') || 0;
		my $res = $stream_results ? $ps->stream : $ps->query;

		die if $wire->get_error_info;

		$sth->STORE('wire10_warning_count', $res->get_warning_count);
		# For backward compatibility and/or do(), store in dbh too.
		my $dbh = $sth->{Database};
		$dbh->STORE('wire10_warning_count', $res->get_warning_count);

		if ($res->has_results) {
			$sth->{wire10_iterator} = $res;
			my @names = $res->get_column_info("name");
			$sth->STORE('NUM_OF_FIELDS', scalar @names);
			$sth->STORE('NAME', [@names]);
			my @flags = $res->get_column_info("flags");
			my @nullable = map { ! $_ & Net::Wire10::COLUMN_NOT_NULL } @flags;
			$sth->STORE('NULLABLE', [@nullable]);
			# DBI docs says this is important for bind_columns and bind_cols.
			$sth->STORE('Active', 1);
			# Note: Emulate DBD-MySQL by not resetting insertid in dbh (only sth).
			$sth->STORE('wire10_insertid', undef);
			$sth->{wire10_rows} = $res->get_no_of_selected_rows;
			return $res->get_no_of_selected_rows;
		} else {
			$sth->{wire10_iterator} = undef;
			$sth->STORE('NUM_OF_FIELDS', undef);
			$sth->STORE('NAME', undef);
			$sth->STORE('NULLABLE', undef);
			my $insertid;
			eval {
				$insertid = $res->get_insert_id;
			};
			if ($@) {
				# If the insert_id is too big for this Perl to handle,
				# extract it using an alternate method.
				my $res = $wire->query('SELECT LAST_INSERT_ID()');
				$insertid = $res->next_array()->[0] || 0;
			}
			$sth->STORE('wire10_insertid', $insertid);
			# For backward compatibility and/or do(), store in dbh too.
			$dbh->STORE('wire10_insertid', $insertid);
			$sth->{wire10_rows} = $res->get_no_of_affected_rows;
			return $res->get_no_of_affected_rows;
		}
	};

	my $error = $wire->get_error_info;
	if ($error) {
		$sth->DBI::set_err($error->get_error_code || -1, $error->get_error_message, $error->get_error_state);
		return undef;
	} elsif ($@) {
		$sth->DBI::set_err(-1, $@);
		return undef;
	}

	return $rowcount ? $rowcount : '0E0';
}

sub cancel {
	my $sth = shift;
	my $wire = $sth->FETCH('wire10_driver_sth');

	eval {
		$wire->cancel;
	};

	if ($@) {
		$sth->DBI::set_err(-1, $@);
		return undef;
	}

	return 1;
}

sub finish {
	my $sth = shift;
	my $dbh = $sth->{Database};
	# If in streaming mode, flush remaining results.
	my $iterator = $sth->{wire10_iterator};
	$iterator->spool if defined $iterator;
	$sth->{wire10_iterator} = undef;
	$sth->STORE('Active', 0);
	$sth->SUPER::finish;
}

sub fetchrow_arrayref {
	my $sth = shift;

	my $iterator = $sth->FETCH('wire10_iterator');
	unless ($iterator) {
		if ($sth->FETCH('Warn')) {
			warn 'fetch() without execute(), previous execute() failed, executed query does not have results, or last row was already fetched';
		}
		return undef;
	}

	my $row = undef;
	eval {
		$row = $iterator->next_array;
	};
	if ($@) {
		$sth->DBI::set_err(-1, $@);
		return undef;
	}
	if (! $row) {
		$sth->finish;
		return undef;
	}

	if ($sth->FETCH('ChopBlanks')) {
		map {s/\s+$//} @$row;
	}

	return $sth->_set_fbav($row);
}

# required alias for fetchrow_arrayref
*fetch = \&fetchrow_arrayref;

sub rows {
	my $sth = shift;
	my $rows = $sth->FETCH('wire10_rows');
	return $rows unless $rows == -1;
	return $sth->SUPER::rows;
}

sub FETCH {
	my $sth = shift;
	my $key = shift;

	return $sth->{NAME} if $key eq 'NAME';
	return $sth->{NULLABLE} if $key eq 'NULLABLE';
	return $sth->{$key} if $key =~ /^wire10_/;
	return $sth->SUPER::FETCH($key);
}

sub STORE {
	my $sth = shift;

lib/DBD/Wire10.pm  view on Meta::CPAN

To bind binary data to a parameter, specify a type such as SQL_BLOB.  This prevents the data from being considered Latin-1 or Unicode text.  Example:

  $sth->bind_param(1, $mydata, SQL_BLOB);

Parameters are numbered beginning from 1.  SQL types are defined as optional exports in DBI:

  use DBI qw(:sql_types);

=head4 execute

Runs a prepared statement, optionally using parameters.  Parameters are supplied either via bind_param(), or directly in the call to execute().  When parameters are given in the call to execute(), they override earlier bound parameters for the durati...

=head4 cancel

Cancels the currently executing statement (or other blocking protocol command, such as C<ping()>).  Safe to call from another thread, but note that DBI currently prevents this.  Safe to call from a signal handler.

Use cancel for interactive code only, where a user may cancel an operation at any time.  Do not use cancel for setting query timeouts.  For that, just set the C<wire10_query_timeout> attribute to an appropriate number of seconds.

Always returns 1 (success).  The actual status of the query (finished or cancelled, depending on timing) appears in the thread which is running the query.

Use C<cancel()> to abort a query when the user presses CTRL-C:

  $SIG{INT} = sub { $sth->cancel; };

Notice that the driver core will terminate the connection when a C<cancel()> is performed.  A call to C<reconnect()> is thus required after a statement has been cancelled in order to reestablish the connection:

  {
    local $SIG{INT} = sub { $sth->cancel; };
    $sth->execute;
  }
  $dbh->reconnect;

If a cancel happens to be performed after the current command has finished executing (in a so-called race condition), it will instead take effect during the next command.  To avoid that the next user query is unduly aborted, a cancel can be flushed o...

=head4 finish

Clears out the resources used by a statement.  This is called automatically at the start of a new query, among other places, and is therefore normally not necessary to call explicitly.

=head4 fetchrow_arrayref

Fetch one row as an array.

There is a multitude of other fetch methods available, such as C<fetchrow_hashref>.  These methods are implemented in DBI, they internally make use of C<fetchrow_arrayref> to retrieve result data.  Refer to the DBI documentation for more information ...

=head4 fetch

Deprecated alias for fetchrow_arrayref.

=head4 rows

The number of affected rows after an UPDATE or similar query, or the number of rows so far read by the client during a SELECT or similar query.

=head3 I<Statement>: attributes

=head4 wire10_insertid

Contains the auto_increment value for the last row inserted.

  my $id = $sth->{wire10_insertid};

=head4 wire10_streaming

If this is set to 1 (or any value that evaluates to true), results will be streamed from the server rather than downloaded all at once, when the statement is executed.

  $sth->{wire10_streaming} = 1;

Notice that the underlying protocol has a limitation: when a streaming statement is active, no other statements can execute on the same connection.

=head4 wire10_warning_count

Contains the number of warnings produced by the last query.

  my $warnings = $sth->{wire10_warning_count};

=head4 ChopBlanks

If enabled, runs every field value in result sets through a regular expression that trims for whitespace.

=head4 NUM_OF_PARAMS

Returns the number of parameter tokens found in the prepared statement after a prepare().

=head4 NUM_OF_FIELDS

Returns the number of columns in the result set after a query has been executed.

  my $numCols = $sth->{NUM_OF_FIELDS};

=head4 NAME

Returns the names of all the columns in the result set after a query has been executed.

=head4 NULLABLE

Returns an array indicating for each column whether it has a NOT NULL constraint.

=head1 TROUBLESHOOTING

=head2 Supported operating systems and Perl versions

Over at CPAN Testers, there's a vast number of testers that do
a very good job of figuring out which versions work together:

L<http://static.cpantesters.org/distro/N/DBD-Wire10.html>

=head2 Differences from DBD-MySQL

=head3 Unicode always enabled

This driver always runs in a mode where international characters outside of the currently active ANSI code page are supported.

=head3 Binary data must be bound

Binary/BLOB data must be given as a bound parameter (see C<bind_param>) using fx. the C<SQL_BLOB> flag.  When using any other method, strings will as a default be interpreted as text.

=head3 Automatic reconnect

Automatic reconnection is not performed when a connection fails mid-execution.  The corresponding DBD-MySQL options C<auto_reconnect> and C<mysql_init_command> are therefore unavailable.

The driver expects you to call C<reconnect()> at any time you wish to check the connection status and (if need be) reestablish a connection with the server.

A good time and place to add a call to C<reconnect()> could be when a connection is first used after a long period of inactivity, plus at any point in your code where it is safe and appropriate to restart processing when an error occurs.

=head3 Automatic numerical trim

Numerical string values bound via C<bind_param()> and provided via C<execute()> parameters are not automatically trimmed of whitespace, even if they look like numbers.

=head3 Various missing protocol features

Various connection methods and other protocol features are not supported by the underlying driver.  See the "Unsupported features" chapter in the L<Net::Wire10> documentation for more information.

=head3 Supported DBI methods and attributes

Some methods are not yet supported in this driver, in particular type_info_all, table_info, column_info, primary_key_info and foreign_key_info.  Some attributes are not yet supported, in particular TYPE.

=head3 Supported C<mysql_> attributes

All of the C<mysql_> attributes are unavailable.  DBI requires that each driver uses a unique prefix, therefore this driver supports only attributes named C<wire10_>.

Not all C<mysql_> attributes have equivalently named C<wire10_> attributes.  For example, there is no C<mysql_use_result> attribute, but one called C<wire10_streaming> does exactly the same.

=head2 Dependencies

This module requires these other modules and libraries:

  L<DBI::DBI>
  L<Net::Wire10>

B<Net::Wire10> is a Pure Perl connector for MySQL, Sphinx and Drizzle servers.

B<Net::Wire10> implements the network protool used to communicate between server and client.

=head1 SEE ALSO

L<DBI::FAQ>
L<DBI::DBI>
L<Net::Wire10>

=head1 AUTHORS

DSN parsing and various code by Hiroyuki OYAMA E, Japan.  DBD boilerplate by DBD authors.  Various code by the open source team at Dubex A/S.

=head1 COPYRIGHT AND LICENCE

Copyright (C) 2002 and (C) 2009 as described in AUTHORS.

This is free software; you can redistribute it and/or modify
it under the same terms as Perl itself. 

=head1 WARRANTY

Because this software is licensed free of charge, there is
absolutely no warranty of any kind, expressed or implied.

=cut



( run in 1.540 second using v1.01-cache-2.11-cpan-140bd7fdf52 )