# Source for file Pgsql.php

Documentation is available at Pgsql.php

1. <?php
2. /*
3. * $Id: Pgsql.php 2033 2007-07-21 15:17:17Z romanb $
4. *
5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16. *
17. * This software consists of voluntary contributions made by many individuals
18. * and is licensed under the LGPL. For more information, see
19. * <http://www.phpdoctrine.com>.
20. */
21. Doctrine::autoload('Doctrine_DataDict');
22. /**
23. * @package Doctrine
24. * @subpackage Doctrine_DataDict
25. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
26. * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
27. * @author Paul Cooper <pgc@ucecom.com>
28. * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
29. * @version $Revision: 2033 $
30. * @category Object Relational Mapping
31. * @link www.phpdoctrine.com
32. * @since 1.0
33. */
34. class Doctrine_DataDict_Pgsql extends Doctrine_DataDict
35. {
36. /**
37. * @param array $reservedKeyWords an array of reserved keywords by pgsql
38. */
39. protected static $reservedKeyWords = array(
40. 'abort',
41. 'absolute',
42. 'access',
43. 'action',
44. 'add',
45. 'after',
46. 'aggregate',
47. 'all',
48. 'alter',
49. 'analyse',
50. 'analyze',
51. 'and',
52. 'any',
53. 'as',
54. 'asc',
55. 'assertion',
56. 'assignment',
57. 'at',
58. 'authorization',
59. 'backward',
60. 'before',
61. 'begin',
62. 'between',
63. 'bigint',
64. 'binary',
65. 'bit',
66. 'boolean',
67. 'both',
68. 'by',
69. 'cache',
70. 'called',
71. 'cascade',
72. 'case',
73. 'cast',
74. 'chain',
75. 'char',
76. 'character',
77. 'characteristics',
78. 'check',
79. 'checkpoint',
80. 'class',
81. 'close',
82. 'cluster',
83. 'coalesce',
84. 'collate',
85. 'column',
86. 'comment',
87. 'commit',
88. 'committed',
89. 'constraint',
90. 'constraints',
91. 'conversion',
92. 'convert',
93. 'copy',
94. 'create',
95. 'createdb',
96. 'createuser',
97. 'cross',
98. 'current_date',
99. 'current_time',
100. 'current_timestamp',
101. 'current_user',
102. 'cursor',
103. 'cycle',
104. 'database',
105. 'day',
106. 'deallocate',
107. 'dec',
108. 'decimal',
109. 'declare',
110. 'default',
111. 'deferrable',
112. 'deferred',
113. 'definer',
114. 'delete',
115. 'delimiter',
116. 'delimiters',
117. 'desc',
118. 'distinct',
119. 'do',
120. 'domain',
121. 'double',
122. 'drop',
123. 'each',
124. 'else',
125. 'encoding',
126. 'encrypted',
127. 'end',
128. 'escape',
129. 'except',
130. 'exclusive',
131. 'execute',
132. 'exists',
133. 'explain',
134. 'external',
135. 'extract',
136. 'false',
137. 'fetch',
138. 'float',
139. 'for',
140. 'force',
141. 'foreign',
142. 'forward',
143. 'freeze',
144. 'from',
145. 'full',
146. 'function',
147. 'get',
148. 'global',
149. 'grant',
150. 'group',
151. 'handler',
152. 'having',
153. 'hour',
154. 'ilike',
155. 'immediate',
156. 'immutable',
157. 'implicit',
158. 'in',
159. 'increment',
160. 'index',
161. 'inherits',
162. 'initially',
163. 'inner',
164. 'inout',
165. 'input',
166. 'insensitive',
167. 'insert',
168. 'instead',
169. 'int',
170. 'integer',
171. 'intersect',
172. 'interval',
173. 'into',
174. 'invoker',
175. 'is',
176. 'isnull',
177. 'isolation',
178. 'join',
179. 'key',
180. 'lancompiler',
181. 'language',
182. 'leading',
183. 'left',
184. 'level',
185. 'like',
186. 'limit',
187. 'listen',
188. 'load',
189. 'local',
190. 'localtime',
191. 'localtimestamp',
192. 'location',
193. 'lock',
194. 'match',
195. 'maxvalue',
196. 'minute',
197. 'minvalue',
198. 'mode',
199. 'month',
200. 'move',
201. 'names',
202. 'national',
203. 'natural',
204. 'nchar',
205. 'new',
206. 'next',
207. 'no',
208. 'nocreatedb',
209. 'nocreateuser',
210. 'none',
211. 'not',
212. 'nothing',
213. 'notify',
214. 'notnull',
215. 'null',
216. 'nullif',
217. 'numeric',
218. 'of',
219. 'off',
220. 'offset',
221. 'oids',
222. 'old',
223. 'on',
224. 'only',
225. 'operator',
226. 'option',
227. 'or',
228. 'order',
229. 'out',
230. 'outer',
231. 'overlaps',
232. 'overlay',
233. 'owner',
234. 'partial',
235. 'password',
236. 'path',
237. 'pendant',
238. 'placing',
239. 'position',
240. 'precision',
241. 'prepare',
242. 'primary',
243. 'prior',
244. 'privileges',
245. 'procedural',
246. 'procedure',
247. 'read',
248. 'real',
249. 'recheck',
250. 'references',
251. 'reindex',
252. 'relative',
253. 'rename',
254. 'replace',
255. 'reset',
256. 'restrict',
257. 'returns',
258. 'revoke',
259. 'right',
260. 'rollback',
261. 'row',
262. 'rule',
263. 'schema',
264. 'scroll',
265. 'second',
266. 'security',
267. 'select',
268. 'sequence',
269. 'serializable',
270. 'session',
271. 'session_user',
272. 'set',
273. 'setof',
274. 'share',
275. 'show',
276. 'similar',
277. 'simple',
278. 'smallint',
279. 'some',
280. 'stable',
281. 'start',
282. 'statement',
283. 'statistics',
284. 'stdin',
285. 'stdout',
286. 'storage',
287. 'strict',
288. 'substring',
289. 'sysid',
290. 'table',
291. 'temp',
292. 'template',
293. 'temporary',
294. 'then',
295. 'time',
296. 'timestamp',
297. 'to',
298. 'toast',
299. 'trailing',
300. 'transaction',
301. 'treat',
302. 'trigger',
303. 'trim',
304. 'true',
305. 'truncate',
306. 'trusted',
307. 'type',
308. 'unencrypted',
309. 'union',
310. 'unique',
311. 'unknown',
312. 'unlisten',
313. 'until',
314. 'update',
315. 'usage',
316. 'user',
317. 'using',
318. 'vacuum',
319. 'valid',
320. 'validator',
321. 'values',
322. 'varchar',
323. 'varying',
324. 'verbose',
325. 'version',
326. 'view',
327. 'volatile',
328. 'when',
329. 'where',
330. 'with',
331. 'without',
332. 'work',
333. 'write',
334. 'year',
335. 'zone'
336. );
338. /**
339. * Obtain DBMS specific SQL code portion needed to declare an text type
340. * field to be used in statements like CREATE TABLE.
341. *
342. * @param array $field associative array with the name of the properties
343. * of the field being declared as array indexes. Currently, the types
344. * of supported field properties are as follows:
345. *
346. * length
347. * Integer value that determines the maximum length of the text
348. * field. If this argument is missing the field should be
349. * declared to have the longest length allowed by the DBMS.
350. *
351. * default
352. * Text value to be used as default for this field.
353. *
354. * notnull
355. * Boolean flag that indicates whether this field is constrained
356. * to not be set to null.
357. *
358. * @return string DBMS specific SQL code portion that should be used to
359. * declare the specified field.
360. */
361. public function getNativeDeclaration(array $field)
362. {
363. if ( ! isset($field['type'])) {
364. throw new Doctrine_DataDict_Exception('Missing column type.');
365. }
366. switch ($field['type']) {
367. case 'char':
368. case 'string':
369. case 'array':
370. case 'object':
371. case 'varchar':
372. case 'gzip':
373. $length = (isset($field['length']) && $field['length']) ? $field['length'] : null;
374. // TODO: $this->conn->options['default_text_field_length'];
376. $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false;
378. return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->options['default_text_field_length'].')')
379. : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
381. case 'clob':
382. return 'TEXT';
383. case 'blob':
384. return 'BYTEA';
385. case 'enum':
386. case 'integer':
387. case 'int':
388. if (!empty($field['autoincrement'])) {
389. if (!empty($field['length'])) {
390. $length = $field['length'];
391. if ($length > 4) {
392. return 'BIGSERIAL';
393. }
394. }
395. return 'SERIAL';
396. }
397. if (!empty($field['length'])) {
398. $length = $field['length'];
399. if ($length <= 2) {
400. return 'SMALLINT';
401. } elseif ($length == 3 || $length == 4) {
402. return 'INT';
403. } elseif ($length > 4) {
404. return 'BIGINT';
405. }
406. }
407. return 'INT';
408. case 'boolean':
409. return 'BOOLEAN';
410. case 'date':
411. return 'DATE';
412. case 'time':
413. return 'TIME without time zone';
414. case 'timestamp':
415. return 'TIMESTAMP without time zone';
416. case 'float':
417. case 'double':
418. return 'FLOAT8';
419. case 'decimal':
420. $length = !empty($field['length']) ? $field['length'] : 18;
421. $scale = !empty($field['scale']) ? $field['scale'] : $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES);
422. return 'NUMERIC('.$length.','.$scale.')';
423. }
424. throw new Doctrine_DataDict_Exception('Unknown field type \'' . $field['type'] . '\'.');
425. }
426. /**
427. * Maps a native array description of a field to a portable Doctrine datatype and length
428. *
429. * @param array $field native field description
430. *
431. * @return array containing the various possible types, length, sign, fixed
432. */
433. public function getPortableDeclaration(array $field)
434. {
436. $length = (isset($field['length'])) ? $field['length'] : null;
437. if ($length == '-1' && isset($field['atttypmod'])) {
438. $length = $field['atttypmod'] - 4;
439. }
440. if ((int)$length <= 0) {
441. $length = null;
442. }
443. $type = array();
444. $unsigned = $fixed = null;
446. if ( ! isset($field['name'])) {
447. $field['name'] = '';
448. }
450. $dbType = strtolower($field['type']);
452. switch ($dbType) {
453. case 'smallint':
454. case 'int2':
455. $type[] = 'integer';
456. $unsigned = false;
457. $length = 2;
458. if ($length == '2') {
459. $type[] = 'boolean';
460. if (preg_match('/^(is|has)/', $field['name'])) {
461. $type = array_reverse($type);
462. }
463. }
464. break;
465. case 'int':
466. case 'int4':
467. case 'integer':
468. case 'serial':
469. case 'serial4':
470. $type[] = 'integer';
471. $unsigned = false;
472. $length = 4;
473. break;
474. case 'bigint':
475. case 'int8':
476. case 'bigserial':
477. case 'serial8':
478. $type[] = 'integer';
479. $unsigned = false;
480. $length = 8;
481. break;
482. case 'bool':
483. case 'boolean':
484. $type[] = 'boolean';
485. $length = 1;
486. break;
487. case 'text':
488. case 'varchar':
489. $fixed = false;
490. case 'unknown':
491. case 'char':
492. case 'bpchar':
493. $type[] = 'string';
494. if ($length == '1') {
495. $type[] = 'boolean';
496. if (preg_match('/^(is|has)/', $field['name'])) {
497. $type = array_reverse($type);
498. }
499. } elseif (strstr($dbType, 'text')) {
500. $type[] = 'clob';
501. }
502. if ($fixed !== false) {
503. $fixed = true;
504. }
505. break;
506. case 'date':
507. $type[] = 'date';
508. $length = null;
509. break;
510. case 'datetime':
511. case 'timestamp':
512. $type[] = 'timestamp';
513. $length = null;
514. break;
515. case 'time':
516. $type[] = 'time';
517. $length = null;
518. break;
519. case 'float':
520. case 'double':
521. case 'real':
522. $type[] = 'float';
523. break;
524. case 'decimal':
525. case 'money':
526. case 'numeric':
527. $type[] = 'decimal';
528. break;
529. case 'tinyblob':
530. case 'mediumblob':
531. case 'longblob':
532. case 'blob':
533. case 'bytea':
534. $type[] = 'blob';
535. $length = null;
536. break;
537. case 'oid':
538. $type[] = 'blob';
539. $type[] = 'clob';
540. $length = null;
541. break;
542. case 'year':
543. $type[] = 'integer';
544. $type[] = 'date';
545. $length = null;
546. break;
547. default:
548. throw new Doctrine_DataDict_Exception('unknown database attribute type: '.$dbType);
549. }
551. return array('type' => $type,
552. 'length' => $length,
553. 'unsigned' => $unsigned,
554. 'fixed' => $fixed);
555. }
556. /**
557. * Obtain DBMS specific SQL code portion needed to declare an integer type
558. * field to be used in statements like CREATE TABLE.
559. *
560. * @param string $name name the field to be declared.
561. * @param array $field associative array with the name of the properties
562. * of the field being declared as array indexes. Currently, the types
563. * of supported field properties are as follows:
564. *
565. * unsigned
566. * Boolean flag that indicates whether the field should be
567. * declared as unsigned integer if possible.
568. *
569. * default
570. * Integer value to be used as default for this field.
571. *
572. * notnull
573. * Boolean flag that indicates whether this field is constrained
574. * to not be set to null.
575. * @return string DBMS specific SQL code portion that should be used to
576. * declare the specified field.
577. */
578. public function getIntegerDeclaration($name, $field)
579. {
580. /**
581. if (!empty($field['unsigned'])) {
582. $this->conn->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
583. }
584. */
586. if ( ! empty($field['autoincrement'])) {
587. $name = $this->conn->quoteIdentifier($name, true);
588. return $name . ' ' . $this->getNativeDeclaration($field);
589. }
591. $default = '';
592. if (array_key_exists('default', $field)) {
593. if ($field['default'] === '') {
594. $field['default'] = empty($field['notnull']) ? null : 0;
595. }
596. $default = ' DEFAULT '.$this->conn->quote($field['default'], $field['type']);
597. }
598. /**
599. TODO: is this needed ?
600. elseif (empty($field['notnull'])) {
601. $default = ' DEFAULT NULL';
602. }
603. */
605. $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
606. $name = $this->conn->quoteIdentifier($name, true);
607. return $name . ' ' . $this->getNativeDeclaration($field) . $default . $notnull;
608. }
609. /**
610. * parseBoolean
611. * parses a literal boolean value and returns
612. * proper sql equivalent
613. *
614. * @param string $value boolean value to be parsed
615. * @return string parsed boolean value
616. */
617. public function parseBoolean($value)
618. {
619. return $value;
620. }
621. }