1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class NSqlPreprocessor extends NObject
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(NConnection $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:
62: $cmd = strtoupper(substr(ltrim($sql), 0, 6));
63: $this->arrayMode = $cmd === 'INSERT' || $cmd === 'REPLAC' ? 'values' : 'assoc';
64:
65: 66: 67: 68: 69:
70: $sql = NStrings::replace($sql, '~\'.*?\'|".*?"|:[a-zA-Z0-9_]+:|\?~s', array($this, 'callback'));
71:
72: while ($this->counter < count($params)) {
73: $sql .= ' ' . $this->formatValue($params[$this->counter++]);
74: }
75:
76: return array($sql, $this->remaining);
77: }
78:
79:
80:
81:
82: public function callback($m)
83: {
84: $m = $m[0];
85: if ($m[0] === "'" || $m[0] === '"') {
86: return $m;
87:
88: } elseif ($m[0] === '?') {
89: return $this->formatValue($this->params[$this->counter++]);
90:
91: } elseif ($m[0] === ':') {
92: $s = substr($m, 1, -1);
93: return isset($this->connection->substitutions[$s]) ? $this->connection->substitutions[$s] : $m;
94: }
95: }
96:
97:
98:
99: private function formatValue($value)
100: {
101: if (is_string($value)) {
102: if (strlen($value) > 20) {
103: $this->remaining[] = $value;
104: return '?';
105:
106: } else {
107: return $this->connection->quote($value);
108: }
109:
110: } elseif (is_int($value)) {
111: return (string) $value;
112:
113: } elseif (is_float($value)) {
114: return rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.');
115:
116: } elseif (is_bool($value)) {
117: $this->remaining[] = $value;
118: return '?';
119:
120: } elseif ($value === NULL) {
121: return 'NULL';
122:
123: } elseif (is_array($value) || $value instanceof Traversable) {
124: $vx = $kx = array();
125:
126: if (isset($value[0])) {
127: foreach ($value as $v) {
128: $vx[] = $this->formatValue($v);
129: }
130: return implode(', ', $vx);
131:
132: } elseif ($this->arrayMode === 'values') {
133: $this->arrayMode = 'multi';
134: foreach ($value as $k => $v) {
135: $kx[] = $this->driver->delimite($k);
136: $vx[] = $this->formatValue($v);
137: }
138: return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
139:
140: } elseif ($this->arrayMode === 'assoc') {
141: foreach ($value as $k => $v) {
142: $vx[] = $this->driver->delimite($k) . '=' . $this->formatValue($v);
143: }
144: return implode(', ', $vx);
145:
146: } elseif ($this->arrayMode === 'multi') {
147: foreach ($value as $k => $v) {
148: $vx[] = $this->formatValue($v);
149: }
150: return ', (' . implode(', ', $vx) . ')';
151: }
152:
153: } elseif ($value instanceof DateTime) {
154: return $this->driver->formatDateTime($value);
155:
156: } elseif ($value instanceof NSqlLiteral) {
157: return $value->value;
158:
159: } else {
160: $this->remaining[] = $value;
161: return '?';
162: }
163: }
164:
165: }
166: