Prepared::getPdoType()   B
last analyzed

Complexity

Conditions 8
Paths 13

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
c 1
b 0
f 0
dl 0
loc 25
rs 8.4444
cc 8
nc 13
nop 2
1
<?php
2
3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2025
6
 * @package Base
7
 * @subpackage DB
8
 */
9
10
11
namespace Aimeos\Base\DB\Statement\PDO;
12
13
14
/**
15
 * Database statement class for prepared PDO statements.
16
 *
17
 * @package Base
18
 * @subpackage DB
19
 */
20
class Prepared extends \Aimeos\Base\DB\Statement\Base implements \Aimeos\Base\DB\Statement\Iface
21
{
22
	private array $binds = [];
23
	private string $sql;
24
25
26
	/**
27
	 * Initializes the statement object
28
	 *
29
	 * @param \Aimeos\Base\DB\Connection\PDO $conn Database connection object
30
	 * @param string $sql SQL statement
31
	 */
32
	public function __construct( \Aimeos\Base\DB\Connection\PDO $conn, string $sql )
33
	{
34
		parent::__construct( $conn );
35
		$this->sql = $sql;
36
	}
37
38
39
	/**
40
	 * Returns the SQL string as sent to the database (magic PHP method)
41
	 *
42
	 * @return string SQL statement
43
	 */
44
	public function __toString()
45
	{
46
		return $this->sql . ":\n" . print_r( array_column( $this->binds, 0 ), true );
0 ignored issues
show
Bug introduced by
Are you sure print_r(array_column($this->binds, 0), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

46
		return $this->sql . ":\n" . /** @scrutinizer ignore-type */ print_r( array_column( $this->binds, 0 ), true );
Loading history...
47
	}
48
49
50
	/**
51
	 * Binds a value to a parameter in the statement
52
	 *
53
	 * @param int $position Position index of the placeholder
54
	 * @param mixed $value Value which should be bound to the placeholder
55
	 * @param int $type Type of given value defined in \Aimeos\Base\DB\Statement\Base as constant
56
	 * @return \Aimeos\Base\DB\Statement\Iface Statement instance for method chaining
57
	 * @throws \Aimeos\Base\DB\Exception If an error occured in the unterlying driver
58
	 */
59
	public function bind( int $position, $value, int $type = \Aimeos\Base\DB\Statement\Base::PARAM_STR ) : \Aimeos\Base\DB\Statement\Iface
60
	{
61
		$this->binds[$position] = [$value, $type];
62
		return $this;
63
	}
64
65
66
	/**
67
	 * Executes the statement
68
	 *
69
	 * @return \Aimeos\Base\DB\Result\Iface Result object
70
	 * @throws \Aimeos\Base\DB\Exception If an error occured in the unterlying driver
71
	 */
72
	public function execute() : \Aimeos\Base\DB\Result\Iface
73
	{
74
		try {
75
			$stmt = $this->exec();
76
		} catch( \PDOException $e ) {
77
			throw new \Aimeos\Base\DB\Exception( $e->getMessage() . ': ' . $this->sql . json_encode( array_column( $this->binds, 0 ) ), $e->getCode(), $e->errorInfo );
78
		}
79
80
		return new \Aimeos\Base\DB\Result\PDO( $stmt );
81
	}
82
83
84
	/**
85
	 * Binds the parameters and executes the SQL statment
86
	 *
87
	 * @return \PDOStatement Executed PDO statement
88
	 */
89
	protected function exec() : \PDOStatement
90
	{
91
		$conn = $this->getConnection();
92
		$stmt = $conn->getRawObject()->prepare( $this->sql );
93
94
		foreach( $this->binds as $position => $list ) {
95
			$stmt->bindValue( $position, $list[0], $this->getPdoType( $list[1], $list[0] ) );
96
		}
97
98
		try
99
		{
100
			$stmt->execute();
101
		}
102
		catch( \PDOException $e )
103
		{
104
			// recover from lost connection (MySQL)
105
			if( !isset( $e->errorInfo[1] ) || $e->errorInfo[1] != 2006 || $conn->inTransaction() === true ) {
106
				throw $e;
107
			}
108
109
			$conn->connect();
110
			return $this->exec();
111
		}
112
113
		return $stmt;
114
	}
115
116
117
	/**
118
	 * Returns the PDO type mapped to the Aimeos type
119
	 *
120
	 * @param integer $type Type of given value defined in \Aimeos\Base\DB\Statement\Base as constant
121
	 * @param mixed $value Value which should be bound to the placeholder
122
	 * @return integer PDO parameter type constant
123
	 * @throws \Aimeos\Base\DB\Exception If the type is unknown
124
	 */
125
	protected function getPdoType( int $type, $value ) : int
126
	{
127
		switch( $type )
128
		{
129
			case \Aimeos\Base\DB\Statement\Base::PARAM_NULL:
130
				$pdotype = \PDO::PARAM_NULL; break;
131
			case \Aimeos\Base\DB\Statement\Base::PARAM_BOOL:
132
				$pdotype = \PDO::PARAM_BOOL; break;
133
			case \Aimeos\Base\DB\Statement\Base::PARAM_INT:
134
				$pdotype = \PDO::PARAM_INT; break;
135
			case \Aimeos\Base\DB\Statement\Base::PARAM_FLOAT:
136
				$pdotype = \PDO::PARAM_STR; break;
137
			case \Aimeos\Base\DB\Statement\Base::PARAM_STR:
138
				$pdotype = \PDO::PARAM_STR; break;
139
			case \Aimeos\Base\DB\Statement\Base::PARAM_LOB:
140
				$pdotype = \PDO::PARAM_LOB; break;
141
			default:
142
				throw new \Aimeos\Base\DB\Exception( sprintf( 'Invalid parameter type "%1$s"', $type ) );
143
		}
144
145
		if( is_null( $value ) ) {
146
			$pdotype = \PDO::PARAM_NULL;
147
		}
148
149
		return $pdotype;
150
	}
151
}
152