1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class SqlPreprocessor extends Object
22: {
23:
24: private $connection;
25:
26:
27: private $driver;
28:
29:
30: private $params;
31:
32:
33: private $remaining;
34:
35:
36: private $counter;
37:
38:
39: private $arrayMode;
40:
41:
42:
43: public function __construct(Connection $connection)
44: {
45: $this->connection = $connection;
46: $this->driver = $connection->getSupplementalDriver();
47: }
48:
49:
50:
51: 52: 53: 54: 55:
56: public function process($sql, $params)
57: {
58: $this->params = $params;
59: $this->counter = 0;
60: $this->remaining = array();
61: $this->arrayMode = 'assoc';
62:
63: $sql = Strings::replace($sql, '~\'.*?\'|".*?"|\?|\b(?:INSERT|REPLACE|UPDATE)\b~si', array($this, 'callback'));
64:
65: while ($this->counter < count($params)) {
66: $sql .= ' ' . $this->formatValue($params[$this->counter++]);
67: }
68:
69: return array($sql, $this->remaining);
70: }
71:
72:
73:
74:
75: public function callback($m)
76: {
77: $m = $m[0];
78: if ($m[0] === "'" || $m[0] === '"') {
79: return $m;
80:
81: } elseif ($m === '?') {
82: return $this->formatValue($this->params[$this->counter++]);
83:
84: } else {
85: $this->arrayMode = strtoupper($m) === 'UPDATE' ? 'assoc' : 'values';
86: return $m;
87: }
88: }
89:
90:
91:
92: private function formatValue($value)
93: {
94: if (is_string($value)) {
95: if (strlen($value) > 20) {
96: $this->remaining[] = $value;
97: return '?';
98:
99: } else {
100: return $this->connection->quote($value);
101: }
102:
103: } elseif (is_int($value)) {
104: return (string) $value;
105:
106: } elseif (is_float($value)) {
107: return rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.');
108:
109: } elseif (is_bool($value)) {
110: $this->remaining[] = $value;
111: return '?';
112:
113: } elseif ($value === NULL) {
114: return 'NULL';
115:
116: } elseif ($value instanceof TableRow) {
117: return $value->getPrimary();
118:
119: } elseif (is_array($value) || $value instanceof Traversable) {
120: $vx = $kx = array();
121:
122: if (isset($value[0])) {
123: foreach ($value as $v) {
124: $vx[] = $this->formatValue($v);
125: }
126: return implode(', ', $vx);
127:
128: } elseif ($this->arrayMode === 'values') {
129: $this->arrayMode = 'multi';
130: foreach ($value as $k => $v) {
131: $kx[] = $this->driver->delimite($k);
132: $vx[] = $this->formatValue($v);
133: }
134: return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
135:
136: } elseif ($this->arrayMode === 'assoc') {
137: foreach ($value as $k => $v) {
138: $vx[] = $this->driver->delimite($k) . '=' . $this->formatValue($v);
139: }
140: return implode(', ', $vx);
141:
142: } elseif ($this->arrayMode === 'multi') {
143: foreach ($value as $k => $v) {
144: $vx[] = $this->formatValue($v);
145: }
146: return '(' . implode(', ', $vx) . ')';
147: }
148:
149: } elseif ($value instanceof DateTime) {
150: return $this->driver->formatDateTime($value);
151:
152: } elseif ($value instanceof SqlLiteral) {
153: return $value->__toString();
154:
155: } else {
156: $this->remaining[] = $value;
157: return '?';
158: }
159: }
160:
161: }
162: