DBD-Teradata

 view release on metacpan or  search on metacpan

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

	$sth->finish
		if $sthp->[26];
	delete $iobj->[1]{$sthp->[12]}
		if defined($sthp->[12]);
	my $params = $attrs->{_fetch_sub} ? undef :
		(scalar @bind_values) ? \@bind_values :
		$sthp->[5];
	$params = delete $attrs->{_residual}
		if $attrs->{_residual};
	my $numParam = $sth->{NUM_OF_PARAMS} || 0;
	if ($sth->{tdat_vartext_in} && ($#bind_values >= 0)) {
		return undef
			unless $sth->bind_param(1, $bind_values[0]);
		$params = $sthp->[5];
	}
	my ($ptypes, $plens, $usephs) =
		($sthp->[2], $sthp->[9], $sthp->[15]);
	my ($sessno, $dbh, $partition) =
		($sth->{tdat_sessno}, $sthp->[23], $iobj->[19]);
	my $loading = (($partition == 5) || ($partition == 4));
	my ($use_cursor, $cursnm, $cursth) = (0, '', undef);
	if ($sth->{Statement}=~/\s+WHERE\s+CURRENT\s+OF\s+([^\s;]+)\s*;?$/i) {
		$cursnm = uc $1;
		$cursth = $dbh->{_cursors}{$cursnm};
		return $sth->DBI::set_err(-1, 'Specified cursor not defined or not updatable.', 'S1000')
			unless $cursth;
		return $sth->DBI::set_err(-1, 'Specified cursor not positioned on a valid row.', 'S1000')
			unless $cursth->{_p}[6];
		$use_cursor = 1;
	}
	$iobj->[14] = 0,
	$sth->{tdat_keepresp} = 1
		if ($sth->{Statement}=~/\s+FOR\s+CURSOR\s*;?$/i);
	my $rawmode = $sth->{tdat_raw_in};
	my $modepcl =
		($partition == 4) ? 104 :
		(($partition == 6) ||
			($rawmode && ($rawmode eq 'RecordMode'))) ? 3 :
				68;
	$numParam = 0
		unless ($partition != 6) ||
			($iobj->[6] && ($#$params >= 0));
	return $sth->DBI::set_err(-1, 'Too many parameters provided.', 'S1000')
		if defined($params) && (@$params > $numParam);
	return $sth->DBI::set_err(-1, 'No parameters provided for parameterized statement.', 'S1000')
		unless ($numParam == 0) || defined($params) || defined($dbh->{tdat_loading}) ||
			$attrs->{_fetch_sub};
	my $stmtno = 0;
	my $maxparmlen = 1;
	if ($attrs->{_fetch_sub}) {
		$maxparmlen = MAX_PARM_TUPLES;
	}
	else {
		foreach (0..$numParam-1) {
			$maxparmlen = scalar(@{$$params[$_]})
				if (ref $$params[$_] eq 'ARRAY') &&
					(scalar(@{$$params[$_]}) > $maxparmlen);
		}
	}
	my $fldcnt = $numParam;
	my ($tuples, $datainfo, $indicdata) = (0, '', '');
	my $pos = 0;
	if (($params && scalar @$params) || $attrs->{_fetch_sub}) {
		($tuples, $datainfo, $indicdata) =
			$usephs ? _process_ph_params($sth, $fldcnt, $params, $attrs) :
				_process_using_params($sth, $fldcnt, $rawmode, $modepcl, $params, $attrs);
		return undef
			unless $tuples;
	}
	$iobj->io_tddo('BT'),
	$iobj->[11] = 1
		if ($partition == 1) && (!$dbh->{AutoCommit}) &&
			($dbh->{tdat_mode} ne 'ANSI') && ($iobj->[11] == 0);
	$iobj->[11] = 1
		if ($partition == 1) && ($dbh->{tdat_mode} eq 'ANSI');
	return $tuples
		if $attrs->{_fetch_sub};
	my $rowcnt = $iobj->io_execute($sth, $datainfo, $indicdata,
		($use_cursor ? $cursth->{_p}[6] : undef));
	$sthp->[13] = $rowcnt;
	return $sth->DBI::set_err($iobj->io_get_error())
		unless defined($rowcnt);
	$sth->{Active} = ($sth->{NUM_OF_FIELDS} != 0);
	undef $sthp->[6]
		if ($sth->{Statement}=~/^DELETE\s+.+\s+WHERE\s+CURRENT\s+OF\s+\w+$/i);
	$sthp->[26] = 1
		unless $sthp->[22] && (! $sth->{tdat_keepresp});
	return ($rowcnt == 0) ? -1 : $rowcnt
		if ($sth->{tdat_compatible} lt '2.0');
	return ($rowcnt == 0) ? '0E0' : $rowcnt;
}
sub _gen_datainfo {
	my ($fldcnt, $ptypes, $plens, $maxszs) = @_;
	my $packstr = '';
	my $datainfo = pack('S', $fldcnt) . ("\0" x ($fldcnt * 4));
	my $prec;
	my $j = 2;
	foreach (0..$fldcnt-1) {
		my $tdtype = $td_type_dbi2code{$ptypes->[$_]}+1;
		$plens->[$_] ||= 0
			if ($ptypes->[$_] == 12) || ($ptypes->[$_] == -3);
		$prec = ($ptypes->[$_] == 3) ?
			$td_decszs[($plens->[$_] >> 8) & 31] : $plens->[$_];
		$packstr .=
			(($ptypes->[$_] == -2) ||
			($ptypes->[$_] == 3))		? "a$prec " :
			($ptypes->[$_] == 1) 		? "A$prec " :
				$td_type_dbi2pack{$ptypes->[$_]} . ' ';
		$prec = 2 + $plens->[$_]
			if ($maxszs->[$_] < $plens->[$_]) &&
				(($ptypes->[$_] == 12) ||
					($ptypes->[$_] == -3));
		substr($datainfo, $j, 4) = pack('SS', $tdtype, $plens->[$_]);
		$maxszs->[$_] = $prec;
		$j += 4;
	}
	return ($datainfo, $packstr);
}
sub _process_ph_params {
	my ($sth, $fldcnt, $params, $attrs) = @_;
	my $indicdata;
	my $pos = 0;
	my $maxsz = 100;
	my ($i, $p);
	my $sthp = $sth->{_p};
	my $iobj = $sthp->[11];
	my $ptypes = $sthp->[2];
	my $plens = $sthp->[9];
	my $fetch_sub = $attrs->{_fetch_sub};
	my @maxszs = ((0) x $fldcnt);
	my ($datainfo, $packstr) = _gen_datainfo($fldcnt, $ptypes, $plens, \@maxszs);
	my @tmpary = ();
	my $ttype = 12;
	my @indicvec = ();
	my $tuples = 0;
	my $deccvt =
		($sth->{tdat_no_bigint} || (!$has_bigint)) ? \&cvt_flt2dec :
		($^O eq 'MSWin32') ? \&cvt_bigint2dec :
		\&cvt_eval_bigint2dec;
	$params = &$fetch_sub()
		unless $params && scalar @$params;
	while ($params) {
		@indicvec = (0xFF) x (($fldcnt & 7) ?
			($fldcnt>>3) + 1 : $fldcnt>>3);
		$pos = 0;
		@tmpary = ();
		foreach (0..$fldcnt-1) {
			$ttype = $ptypes->[$_];
			$p = $params->[$_];
			$p = (ref $p eq 'ARRAY') ? $p->[0] : $$p
				if defined($p) && (ref $p);
			push(@tmpary, $nullvals{$ttype}),
			$pos +=
				(($ttype == 12) ||
				($ttype == -3))	? 2 : $maxszs[$_],
			next
				unless defined($p);
			$indicvec[$_>>3] &= $td_indicmasks[$_ & 7],
			push(@tmpary,
				($ttype == 3)				? $deccvt->($p, $plens->[$_]) :
				(($ttype == 6) && $use_arm) ? cvt_arm_flt($p) : $p);
			$pos +=
				(($ttype == 12) ||
				($ttype == -3))	? 2 + length($p) :
				($ttype == 3)		? $td_decszs[(($plens->[$_]>>8) & 31)] :
				$plens->[$_];
			$maxszs[$_] = length($p) + 2,
			substr($datainfo, 4 + ($_ << 2), 2, pack('S', $maxszs[$_]))
				if (($ttype == 12) || ($ttype == -3)) &&
					($maxszs[$_] < length($p) + 2);
		}
		map { $maxsz += $_; } @maxszs;
		$maxsz += scalar @indicvec;
		$indicdata = "\0" x $maxsz;
		substr($indicdata, 0, scalar(@indicvec), pack('C*', @indicvec));
		substr($indicdata, scalar(@indicvec), $pos, pack($packstr, @tmpary));
		$pos += scalar(@indicvec);
		return (++$tuples, $datainfo, substr($indicdata, 0, $pos))
			;
	}
	substr($iobj->[16], $attrs->{_datainfop}, length($datainfo), $datainfo);
	return ($tuples, undef, undef);
}
sub _process_using_params {
	my ($sth, $fldcnt, $rawmode, $modepcl, $params, $attrs) = @_;
	my $indicdata;
	my $pos = 0;
	my $maxsz = (($fldcnt & 7) ? ($fldcnt>>3) + 1 : $fldcnt>>3);
	my ($i, $k, $p);
	my $sthp = $sth->{_p};
	my $iobj = $sthp->[11];
	my $ptypes = $sthp->[2];
	my $plens = $sthp->[9];
	my $packstr = $sthp->[18];
	my $fetch_sub = $attrs->{_fetch_sub};
	my $tuples = 0;
	my $deccvt =
		($sth->{tdat_no_bigint} || (!$has_bigint)) ? \&cvt_flt2dec :
		($^O eq 'MSWin32') ? \&cvt_bigint2dec :
		\&cvt_eval_bigint2dec;
	unless ($rawmode) {
		for ($i = 0; $i < $fldcnt; $i++) {
			$maxsz += (($ptypes->[$i] == 3) ?
				$td_decszs[(($plens->[$i]>>8) & 31)] : $plens->[$i]);
			$maxsz += 2
				if ($ptypes->[$i] == 12) || ($ptypes->[$i] == -3);
		}
	}
	my @tmpary = ();
	my $ttype = 12;
	my @indicvec = ();
	$params = &$fetch_sub()
		unless $params && scalar @$params;
	my $is_vartext = $sth->{tdat_vartext_in};
	my @ps;
	my $notbar = ($is_vartext && ($is_vartext eq '|')) ? undef : $is_vartext;
	while ($params) {
		if ($is_vartext && (scalar @$params == 1)) {
			@$params = $notbar ? split($notbar, $params->[0]) : split('\|', $params->[0]);
			foreach (0..$fldcnt-1) {
				$plens->[$_] = length($params->[$_])
					if defined($params->[$_]) && ($plens->[$_] < length($params->[$_]));
			}
		}
		unless ($rawmode) {
			@indicvec = (0xFF) x (($fldcnt & 7) ? ($fldcnt>>3) + 1 : $fldcnt>>3);
			$pos = 0;
			@tmpary = ();
			foreach (0..$fldcnt-1) {
				$ttype = $ptypes->[$_];
				$p = $params->[$_];
				$p = (ref $p eq 'ARRAY') ? $p->[0] : $$p
					if defined($p) && (ref $p);
				push(@tmpary, $nullvals{$ttype}),
				$pos +=
					(($ttype == 12) ||
					($ttype == -3))	? 2 :
					($ttype == 3)		? $td_decszs[($plens->[$_] >> 8) & 31] :
						$plens->[$_],
				next
					unless defined($p);
				$indicvec[$_>>3] &= $td_indicmasks[$_ & 7],
				push(@tmpary,
					($ttype == 3)				? $deccvt->($p, $plens->[$_]) :
					(($ttype == 6) && $use_arm) ? cvt_arm_flt($p) : $p);
				$pos +=
					(($ttype == 12) ||
					($ttype == -3))	? 2 + length($p) :
					($ttype == 3)		? $td_decszs[(($plens->[$_]>>8) & 31)] :
					$plens->[$_];
					$ttype = $ptypes->[$i];
					$p = $params->[$i];
					$p = $$p
						if defined($p) && (ref $p);
			}
			$indicdata = "\0" x $maxsz;
			substr($indicdata, 0, scalar(@indicvec), pack('C*', @indicvec));
			substr($indicdata, scalar(@indicvec), $pos, pack($packstr, @tmpary));
			$pos += scalar(@indicvec);
		}
		else {
			$p = $params->[0];
			$p = (ref $p eq 'ARRAY') ? $p->[0] : $$p
				if defined($p) && (ref $p);
			$pos = length($p) - 3;
			$indicdata = substr($p, 2, $pos);
		}
		return (++$tuples, undef, substr($indicdata, 0, $pos))
		;
	}
	return ($tuples, undef, undef);
}
sub Realize {
	return defined($_[0]->{_p}[11]->io_Realize($_[0])) ?
		1 : $_[0]->DBI::set_err($_[0]->{_p}[11]->io_get_error());
}
*tdat_Realize = \&Realize;
sub tdat_Rewind {
	return $_[0]->{_p}[11]->io_rewind($_[0]);
}
sub fetch {
	return $_[0]->tdat_Unpack();
}
sub tdat_Unpack {
	my ($sth, $rec, $recmode) = @_;
	my $sthp = $sth->{_p};
	my $sessno = $sth->{tdat_sessno};
	my $stmtno = $sth->{tdat_stmt_num};
	my $nowait = $sth->{tdat_nowait};
	my $stmtinfo = $sth->{tdat_stmt_info};
	my $rawmode = $sth->{tdat_raw_out};
	my $vartext = $sth->{tdat_vartext_out};
	my $colary = $sthp->[1];
	my $maxlen = $sthp->[14];
	my $iobj = $sthp->[11];
	my $data = '';
	my @tmpary = ();
	my $ary = (defined($colary) ? ($rawmode ? $$colary[0] : \@tmpary) : undef);
	my $rc;
	if (defined($rec)) {
		$data = $rec;
		$rc = 1;
	}
	else {
		$rc = $iobj->io_fetch($sth, $ary, \$data);
		return $sth->DBI::set_err($iobj->io_get_error())
			unless defined($rc);
		$sth->{Active} = undef
			unless ($rc > 0) || $sth->{tdat_more_results};
		return $rc if ($rc <= 0);
	}
	my $loopcnt = $rc;
	my $ftypes = $sth->{TYPE};
	my $fprec = $sth->{PRECISION};
	my $fscale = $sth->{SCALE};
	my $stmthash = $$stmtinfo[$stmtno];
	my $isCall = ($stmthash->{ActivityType} eq 'Call');
	my $actends = $stmthash->{EndsAt};
	my $actstarts = $stmthash->{StartsAt};
	my $actsumstarts = $stmthash->{SummaryStarts};
	my $actsumends = $stmthash->{SummaryEnds};
	my $issum = $stmthash->{IsSummary};
	my $numflds = defined($issum) ?
		$$actsumends[$issum] - $$actsumstarts[$issum] + 1 :
		$actends - $actstarts + 1;
	my $unpackstr = $sthp->[10][
		(defined($issum) ? $$actsumstarts[$issum] : $actstarts)];
	my $ibytes = ((($numflds & 7) !=  0) ? ($numflds>>3) + 1 : $numflds>>3);

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

					next
						unless ($datatype & 3);
					$$parmdesc[$$parmnum] |= 4;
					$$parmmap{$$phnum} = $nextcol
						if ($$parmdesc[$$parmnum] & 1);
					$$parmnum++;
					$stmtinfo->{EndsAt} = $nextcol;
				}
				$datatype &= 0xfffc;
			}
			$sthargs->{NAME}[$nextcol] = ($cname eq '') ?
				(($ctitle eq '') ? "COLUMN$nextcol" : $ctitle) :
				$cname;
			my $ttype = $sthargs->{TYPE}[$nextcol] =
				$td_type_code2dbi{$datatype & 0xfffe};
			$sthargs->{NULLABLE}[$nextcol] = ($activity == 105) ?
				1 : $datatype & 1;
			$sthargs->{tdat_TITLE}[$nextcol] = $ctitle;
			$cfmt = uc $cfmt;
			$cfmt = '-(' . (length($1) + 1) . ")$2"
				if ($cfmt=~/^(-+)(.*)/);
			$sthargs->{tdat_FORMAT}[$nextcol] = $cfmt;
			my $prec = $sthargs->{PRECISION}[$nextcol] = ($ttype == 3) ?
				(($datalen >> 8) & 31) : $datalen;
			my $scale = $sthargs->{SCALE}[$nextcol] = ($ttype == 3) ?
				($datalen & 255) : 0;
			my $len = ($ttype == 3) ? $td_decszs[$prec] : $datalen;
			$packstr .=
				(($ttype == -2) || ($ttype == 3)) ? "a$len " :
				(($ttype == 1)								? "A$len " :
					($td_type_dbi2pack{$ttype}) . ' ');
			$sthargs->{tdat_FORMAT}[$nextcol] = "6($prec)"
				if ($ttype == -2) || ($ttype == -3);
			my $typestr = $td_type_dbi2str{$ttype};
			$typestr .= '(' . $prec .
				(($ttype == 3) ? ", $scale)" : ')')
				if $td_type_str2baseprec{$typestr};
			$sthargs->{tdat_TYPESTR}[$nextcol] = $typestr;
			DBI->trace_msg(
				($ttype != 3) ?
		"$sthargs->{NAME}[$nextcol]\: $ttype LENGTH $prec\n" :
		"$sthargs->{NAME}[$nextcol]\: DECIMAL($prec, $scale) LENGTH $td_decszs[$len]\n",
					1)
				if $debug;
		}
		my $packidx = $nextsum ? $stmtinfo->{SummaryStarts}[$nextsum - 1] : $stmtinfo->{StartsAt};
		$packstr=~s/\*//g;
		$sthargs->{_unpackstr}[$packidx] = $packstr;
		$packstr = '';
		last unless $sumcnt;
		$colcnt = unpack('S', substr($pcl, $curpos));
		$stmtinfo->{SummaryStarts}[$nextsum] = $nextcol;
		$stmtinfo->{SummaryEnds}[$nextsum] = $nextcol + $colcnt - 1;
		$nextsum++;
		$curpos += 2;
		$sumcnt--;
	}
	return $nextcol;
}
sub io_execute {
	my ($obj, $sth, $datainfo, $indicdata, $rowid) = @_;
	$obj->[18] = 0;
	$obj->[24] = '00000';
	$obj->[17] = '';
	my $stmtinfo = $sth->{tdat_stmt_info};
	my $stmtno = $sth->{tdat_stmtno};
	my $nowait = $sth->{tdat_nowait};
	my $stmt = $sth->{Statement} || '';
	my $keepresp = ($sth->{tdat_keepresp} || ($stmt=~/\s+FOR\s+CURSOR\s*$/i));
	my $rawmode = $sth->{tdat_raw_in};
	my $reqmsg = '';
	my $reqlen = 0;
	my $modepcl = ($rawmode && defined($rawmodes{$rawmode})) ?
		$rawmodes{$rawmode} : 68;
	my $partition = $obj->[19];
	my $reqfac = $obj->[38];
	$stmt=~s/\s+WHERE\s+CURRENT\s+OF\s+([^\s;]+)\s*;?\s*$/ WHERE CURRENT/i;
	my $forCursor = ($stmt=~/\s+WHERE\s+CURRENT$/i) && $rowid;
	if (($partition == 1) ||
		(($partition == 6) && ($stmt ne ';'))) {
		$reqlen = 4 + length($stmt) + 6 +
			((defined($datainfo) && length($datainfo)) ? 4 + length($datainfo) : 0) +
			((defined($indicdata) && length($indicdata)) ? 4 + length($indicdata) : 0) +
			($forCursor ? 4 + length($rowid) : 0) +
			($sth->{tdat_mload} ? 14 : 0);
		if ($reqlen > 65535) {
			$reqlen += 4 + 4 + (length($datainfo) ? 4 : 0) +
				(length($indicdata) ? 4 : 0) + (($forCursor && $rowid) ? 4 : 0);
			$obj->[26] = 1;
		}
		else {
			$obj->[26] = undef;
		}
	}
	if ($sth->{Statement}=~/^\s*(CREATE|REPLACE)\s+PROCEDURE\s+/i) {
		my $pos = 0;
		my $segment = 1;
		my $len = length($sth->{Statement});
		my $sz = 0;
		while ($len) {
			$sz = ($len > 64000) ? 64000 : $len;
			$len -= $sz;
			($reqmsg, $pos) = $reqfac->spRequest($obj, $sz, $pos, $segment, $sth, $obj->[3]);
			$segment++;
			my $treqno = $obj->[2];
			$obj->io_quicksend(length($reqmsg), undef, $reqmsg) or return undef;
			$obj->[1]{$treqno} = $sth;
			$sth->{_p}[12] = $treqno;
			last unless $len;
			return undef unless defined($obj->io_Realize($sth));
		}
		return ($nowait ? -1 : $obj->io_Realize($sth));
	}
	return $obj->io_set_error('Maximum request size exceeded.')
		if ($obj->[40] < 5000000) && ($reqlen > 65535);
	if ($partition == 1) {
		$reqmsg = $reqfac->sqlRequest($obj, $sth, $forCursor, $rowid, $modepcl, $keepresp,
			$obj->[3], $stmt, $datainfo, $indicdata);
	}
	delete $obj->[1]{$_}
		foreach (keys %{$obj->[1]});
	my $treqno = $obj->[2];
	if (($partition == 5) || ($partition == 4)) {
		$obj->io_quicksend($obj->[32], undef, $obj->[16])
			or return undef;
	}
	else {
		$obj->io_tdsend($reqmsg) or return undef;
	}
	$obj->[1]{$treqno} = $sth;
	$sth->{_p}[12] = $treqno;
	return ($nowait) ? -1 : $obj->io_Realize($sth);
}
sub io_fetch {
	my ($obj, $sth, $ary, $retstr) = @_;
	$obj->[18] = 0;
	$obj->[24] = '00000';
	$obj->[17] = '';
	my $sthp = $sth->{_p};
	return 0 unless $sthp->[17];
	my $maxlen = ($ary) ? $sthp->[14] : 1;
	my $stmtno = $sth->{tdat_stmt_num};
	my ($f, $l, $failed) = (0,0,0,0);
	my $rspmsg = $sthp->[17];
	my $pos = $sthp->[19];
	my $rsplen = ($$rspmsg) ? length($$rspmsg) : 0;
	my $partition = $obj->[19];
	my $stmtinfo = $sth->{tdat_stmt_info};
	my $stmthash = ($stmtno) ? $$stmtinfo[$stmtno] : undef;
	my $endstmt = 0;
	my $total_activity = 0;
	my $arycnt = 0;
	if ($pos >= $rsplen) {
		$rspmsg = $obj->io_tdcontinue($sth, 0);
		return 0 unless $$rspmsg;
		$sthp->[17] = $rspmsg;
		$rsplen = length($$rspmsg);
		$obj->io_tdcontinue($sth, 1)
			if (! $sthp->[22]) && $obj->[14];
		$pos = 52;
	}
	my ($pclhdrsz, $rowcnt, $tderr, $fldcount, $activity, $tdelen, $tdemsg);
	($f, $l, $pclhdrsz) = _getPclHeader($$rspmsg, $pos);
	$sth->{tdat_more_results} = 1;
	while (($f != 10) && ($f != 105)) {
		$sthp->[19] = $pos + $l;
		if ($f == 12) {
			$sthp->[17] = undef;
			$sthp->[19] = 0;
			$sth->{tdat_more_results} = 0;
			$obj->io_tddo('COMMIT WORK'),
			$obj->[11] = 0
				if ($obj->[10] eq 'ANSI') &&
					$obj->[11] && $obj->[31]{AutoCommit};
			$sth->{tdat_more_results} = 0,
			delete $obj->[1]{$sthp->[12]},
			$sthp->[12] = 0,
				unless ($obj->[19] == 3) ||



( run in 1.168 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )