AbstractPlatform.php 69KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. *
  15. * This software consists of voluntary contributions made by many individuals
  16. * and is licensed under the LGPL. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\DBAL\Platforms;
  20. use Doctrine\DBAL\DBALException,
  21. Doctrine\DBAL\Connection,
  22. Doctrine\DBAL\Types,
  23. Doctrine\DBAL\Schema\Table,
  24. Doctrine\DBAL\Schema\Index,
  25. Doctrine\DBAL\Schema\ForeignKeyConstraint,
  26. Doctrine\DBAL\Schema\TableDiff,
  27. Doctrine\DBAL\Schema\Column,
  28. Doctrine\DBAL\Types\Type;
  29. /**
  30. * Base class for all DatabasePlatforms. The DatabasePlatforms are the central
  31. * point of abstraction of platform-specific behaviors, features and SQL dialects.
  32. * They are a passive source of information.
  33. *
  34. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
  35. * @link www.doctrine-project.org
  36. * @since 2.0
  37. * @version $Revision: 3938 $
  38. * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
  39. * @author Jonathan Wage <jonwage@gmail.com>
  40. * @author Roman Borschel <roman@code-factory.org>
  41. * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
  42. * @author Benjamin Eberlei <kontakt@beberlei.de>
  43. * @todo Remove any unnecessary methods.
  44. */
  45. abstract class AbstractPlatform
  46. {
  47. /**
  48. * @var int
  49. */
  50. const CREATE_INDEXES = 1;
  51. /**
  52. * @var int
  53. */
  54. const CREATE_FOREIGNKEYS = 2;
  55. /**
  56. * @var int
  57. */
  58. const TRIM_UNSPECIFIED = 0;
  59. /**
  60. * @var int
  61. */
  62. const TRIM_LEADING = 1;
  63. /**
  64. * @var int
  65. */
  66. const TRIM_TRAILING = 2;
  67. /**
  68. * @var int
  69. */
  70. const TRIM_BOTH = 3;
  71. /**
  72. * @var array
  73. */
  74. protected $doctrineTypeMapping = null;
  75. /**
  76. * Contains a list of all columns that should generate parseable column comments for type-detection
  77. * in reverse engineering scenarios.
  78. *
  79. * @var array
  80. */
  81. protected $doctrineTypeComments = null;
  82. /**
  83. * Constructor.
  84. */
  85. public function __construct() {}
  86. /**
  87. * Gets the SQL snippet that declares a boolean column.
  88. *
  89. * @param array $columnDef
  90. * @return string
  91. */
  92. abstract public function getBooleanTypeDeclarationSQL(array $columnDef);
  93. /**
  94. * Gets the SQL snippet that declares a 4 byte integer column.
  95. *
  96. * @param array $columnDef
  97. * @return string
  98. */
  99. abstract public function getIntegerTypeDeclarationSQL(array $columnDef);
  100. /**
  101. * Gets the SQL snippet that declares an 8 byte integer column.
  102. *
  103. * @param array $columnDef
  104. * @return string
  105. */
  106. abstract public function getBigIntTypeDeclarationSQL(array $columnDef);
  107. /**
  108. * Gets the SQL snippet that declares a 2 byte integer column.
  109. *
  110. * @param array $columnDef
  111. * @return string
  112. */
  113. abstract public function getSmallIntTypeDeclarationSQL(array $columnDef);
  114. /**
  115. * Gets the SQL snippet that declares common properties of an integer column.
  116. *
  117. * @param array $columnDef
  118. * @return string
  119. */
  120. abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef);
  121. /**
  122. * Lazy load Doctrine Type Mappings
  123. *
  124. * @return void
  125. */
  126. abstract protected function initializeDoctrineTypeMappings();
  127. /**
  128. * Gets the SQL snippet used to declare a VARCHAR column type.
  129. *
  130. * @param array $field
  131. */
  132. public function getVarcharTypeDeclarationSQL(array $field)
  133. {
  134. if ( !isset($field['length'])) {
  135. $field['length'] = $this->getVarcharDefaultLength();
  136. }
  137. $fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
  138. if ($field['length'] > $this->getVarcharMaxLength()) {
  139. return $this->getClobTypeDeclarationSQL($field);
  140. } else {
  141. return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed);
  142. }
  143. }
  144. protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed)
  145. {
  146. throw DBALException::notSupported('VARCHARs not supported by Platform.');
  147. }
  148. /**
  149. * Gets the SQL snippet used to declare a CLOB column type.
  150. *
  151. * @param array $field
  152. */
  153. abstract public function getClobTypeDeclarationSQL(array $field);
  154. /**
  155. * Gets the name of the platform.
  156. *
  157. * @return string
  158. */
  159. abstract public function getName();
  160. /**
  161. * Register a doctrine type to be used in conjunction with a column type of this platform.
  162. *
  163. * @param string $dbType
  164. * @param string $doctrineType
  165. */
  166. public function registerDoctrineTypeMapping($dbType, $doctrineType)
  167. {
  168. if ($this->doctrineTypeMapping === null) {
  169. $this->initializeDoctrineTypeMappings();
  170. }
  171. if (!Types\Type::hasType($doctrineType)) {
  172. throw DBALException::typeNotFound($doctrineType);
  173. }
  174. $dbType = strtolower($dbType);
  175. $this->doctrineTypeMapping[$dbType] = $doctrineType;
  176. }
  177. /**
  178. * Get the Doctrine type that is mapped for the given database column type.
  179. *
  180. * @param string $dbType
  181. * @return string
  182. */
  183. public function getDoctrineTypeMapping($dbType)
  184. {
  185. if ($this->doctrineTypeMapping === null) {
  186. $this->initializeDoctrineTypeMappings();
  187. }
  188. $dbType = strtolower($dbType);
  189. if (isset($this->doctrineTypeMapping[$dbType])) {
  190. return $this->doctrineTypeMapping[$dbType];
  191. } else {
  192. throw new \Doctrine\DBAL\DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it.");
  193. }
  194. }
  195. /**
  196. * Check if a database type is currently supported by this platform.
  197. *
  198. * @param string $dbType
  199. * @return bool
  200. */
  201. public function hasDoctrineTypeMappingFor($dbType)
  202. {
  203. if ($this->doctrineTypeMapping === null) {
  204. $this->initializeDoctrineTypeMappings();
  205. }
  206. $dbType = strtolower($dbType);
  207. return isset($this->doctrineTypeMapping[$dbType]);
  208. }
  209. /**
  210. * Initialize the Doctrine Type comments instance variable for in_array() checks.
  211. *
  212. * @return void
  213. */
  214. protected function initializeCommentedDoctrineTypes()
  215. {
  216. $this->doctrineTypeComments = array(Type::TARRAY, Type::OBJECT);
  217. }
  218. /**
  219. * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type?
  220. *
  221. * @param Type $doctrineType
  222. * @return bool
  223. */
  224. public function isCommentedDoctrineType(Type $doctrineType)
  225. {
  226. if ($this->doctrineTypeComments === null) {
  227. $this->initializeCommentedDoctrineTypes();
  228. }
  229. return in_array($doctrineType->getName(), $this->doctrineTypeComments);
  230. }
  231. /**
  232. * Mark this type as to be commented in ALTER TABLE and CREATE TABLE statements.
  233. *
  234. * @param Type $doctrineType
  235. * @return void
  236. */
  237. public function markDoctrineTypeCommented(Type $doctrineType)
  238. {
  239. if ($this->doctrineTypeComments === null) {
  240. $this->initializeCommentedDoctrineTypes();
  241. }
  242. $this->doctrineTypeComments[] = $doctrineType->getName();
  243. }
  244. /**
  245. * Get the comment to append to a column comment that helps parsing this type in reverse engineering.
  246. *
  247. * @param Type $doctrineType
  248. * @return string
  249. */
  250. public function getDoctrineTypeComment(Type $doctrineType)
  251. {
  252. return '(DC2Type:' . $doctrineType->getName() . ')';
  253. }
  254. /**
  255. * Return the comment of a passed column modified by potential doctrine type comment hints.
  256. *
  257. * @param Column $column
  258. * @return string
  259. */
  260. protected function getColumnComment(Column $column)
  261. {
  262. $comment = $column->getComment();
  263. if ($this->isCommentedDoctrineType($column->getType())) {
  264. $comment .= $this->getDoctrineTypeComment($column->getType());
  265. }
  266. return $comment;
  267. }
  268. /**
  269. * Gets the character used for identifier quoting.
  270. *
  271. * @return string
  272. */
  273. public function getIdentifierQuoteCharacter()
  274. {
  275. return '"';
  276. }
  277. /**
  278. * Gets the string portion that starts an SQL comment.
  279. *
  280. * @return string
  281. */
  282. public function getSqlCommentStartString()
  283. {
  284. return "--";
  285. }
  286. /**
  287. * Gets the string portion that ends an SQL comment.
  288. *
  289. * @return string
  290. */
  291. public function getSqlCommentEndString()
  292. {
  293. return "\n";
  294. }
  295. /**
  296. * Gets the maximum length of a varchar field.
  297. *
  298. * @return integer
  299. */
  300. public function getVarcharMaxLength()
  301. {
  302. return 4000;
  303. }
  304. /**
  305. * Gets the default length of a varchar field.
  306. *
  307. * @return integer
  308. */
  309. public function getVarcharDefaultLength()
  310. {
  311. return 255;
  312. }
  313. /**
  314. * Gets all SQL wildcard characters of the platform.
  315. *
  316. * @return array
  317. */
  318. public function getWildcards()
  319. {
  320. return array('%', '_');
  321. }
  322. /**
  323. * Returns the regular expression operator.
  324. *
  325. * @return string
  326. */
  327. public function getRegexpExpression()
  328. {
  329. throw DBALException::notSupported(__METHOD__);
  330. }
  331. /**
  332. * Returns the average value of a column
  333. *
  334. * @param string $column the column to use
  335. * @return string generated sql including an AVG aggregate function
  336. */
  337. public function getAvgExpression($column)
  338. {
  339. return 'AVG(' . $column . ')';
  340. }
  341. /**
  342. * Returns the number of rows (without a NULL value) of a column
  343. *
  344. * If a '*' is used instead of a column the number of selected rows
  345. * is returned.
  346. *
  347. * @param string|integer $column the column to use
  348. * @return string generated sql including a COUNT aggregate function
  349. */
  350. public function getCountExpression($column)
  351. {
  352. return 'COUNT(' . $column . ')';
  353. }
  354. /**
  355. * Returns the highest value of a column
  356. *
  357. * @param string $column the column to use
  358. * @return string generated sql including a MAX aggregate function
  359. */
  360. public function getMaxExpression($column)
  361. {
  362. return 'MAX(' . $column . ')';
  363. }
  364. /**
  365. * Returns the lowest value of a column
  366. *
  367. * @param string $column the column to use
  368. * @return string
  369. */
  370. public function getMinExpression($column)
  371. {
  372. return 'MIN(' . $column . ')';
  373. }
  374. /**
  375. * Returns the total sum of a column
  376. *
  377. * @param string $column the column to use
  378. * @return string
  379. */
  380. public function getSumExpression($column)
  381. {
  382. return 'SUM(' . $column . ')';
  383. }
  384. // scalar functions
  385. /**
  386. * Returns the md5 sum of a field.
  387. *
  388. * Note: Not SQL92, but common functionality
  389. *
  390. * @return string
  391. */
  392. public function getMd5Expression($column)
  393. {
  394. return 'MD5(' . $column . ')';
  395. }
  396. /**
  397. * Returns the length of a text field.
  398. *
  399. * @param string $expression1
  400. * @param string $expression2
  401. * @return string
  402. */
  403. public function getLengthExpression($column)
  404. {
  405. return 'LENGTH(' . $column . ')';
  406. }
  407. /**
  408. * Rounds a numeric field to the number of decimals specified.
  409. *
  410. * @param string $expression1
  411. * @param string $expression2
  412. * @return string
  413. */
  414. public function getRoundExpression($column, $decimals = 0)
  415. {
  416. return 'ROUND(' . $column . ', ' . $decimals . ')';
  417. }
  418. /**
  419. * Returns the remainder of the division operation
  420. * $expression1 / $expression2.
  421. *
  422. * @param string $expression1
  423. * @param string $expression2
  424. * @return string
  425. */
  426. public function getModExpression($expression1, $expression2)
  427. {
  428. return 'MOD(' . $expression1 . ', ' . $expression2 . ')';
  429. }
  430. /**
  431. * Trim a string, leading/trailing/both and with a given char which defaults to space.
  432. *
  433. * @param string $str
  434. * @param int $pos
  435. * @param string $char has to be quoted already
  436. * @return string
  437. */
  438. public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
  439. {
  440. $posStr = '';
  441. $trimChar = ($char != false) ? $char . ' FROM ' : '';
  442. if ($pos == self::TRIM_LEADING) {
  443. $posStr = 'LEADING '.$trimChar;
  444. } else if($pos == self::TRIM_TRAILING) {
  445. $posStr = 'TRAILING '.$trimChar;
  446. } else if($pos == self::TRIM_BOTH) {
  447. $posStr = 'BOTH '.$trimChar;
  448. }
  449. return 'TRIM(' . $posStr . $str . ')';
  450. }
  451. /**
  452. * rtrim
  453. * returns the string $str with proceeding space characters removed
  454. *
  455. * @param string $str literal string or column name
  456. * @return string
  457. */
  458. public function getRtrimExpression($str)
  459. {
  460. return 'RTRIM(' . $str . ')';
  461. }
  462. /**
  463. * ltrim
  464. * returns the string $str with leading space characters removed
  465. *
  466. * @param string $str literal string or column name
  467. * @return string
  468. */
  469. public function getLtrimExpression($str)
  470. {
  471. return 'LTRIM(' . $str . ')';
  472. }
  473. /**
  474. * upper
  475. * Returns the string $str with all characters changed to
  476. * uppercase according to the current character set mapping.
  477. *
  478. * @param string $str literal string or column name
  479. * @return string
  480. */
  481. public function getUpperExpression($str)
  482. {
  483. return 'UPPER(' . $str . ')';
  484. }
  485. /**
  486. * lower
  487. * Returns the string $str with all characters changed to
  488. * lowercase according to the current character set mapping.
  489. *
  490. * @param string $str literal string or column name
  491. * @return string
  492. */
  493. public function getLowerExpression($str)
  494. {
  495. return 'LOWER(' . $str . ')';
  496. }
  497. /**
  498. * returns the position of the first occurrence of substring $substr in string $str
  499. *
  500. * @param string $substr literal string to find
  501. * @param string $str literal string
  502. * @param int $pos position to start at, beginning of string by default
  503. * @return integer
  504. */
  505. public function getLocateExpression($str, $substr, $startPos = false)
  506. {
  507. throw DBALException::notSupported(__METHOD__);
  508. }
  509. /**
  510. * Returns the current system date.
  511. *
  512. * @return string
  513. */
  514. public function getNowExpression()
  515. {
  516. return 'NOW()';
  517. }
  518. /**
  519. * return string to call a function to get a substring inside an SQL statement
  520. *
  521. * Note: Not SQL92, but common functionality.
  522. *
  523. * SQLite only supports the 2 parameter variant of this function
  524. *
  525. * @param string $value an sql string literal or column name/alias
  526. * @param integer $from where to start the substring portion
  527. * @param integer $len the substring portion length
  528. * @return string
  529. */
  530. public function getSubstringExpression($value, $from, $len = null)
  531. {
  532. if ($len === null)
  533. return 'SUBSTRING(' . $value . ' FROM ' . $from . ')';
  534. else {
  535. return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $len . ')';
  536. }
  537. }
  538. /**
  539. * Returns a series of strings concatinated
  540. *
  541. * concat() accepts an arbitrary number of parameters. Each parameter
  542. * must contain an expression
  543. *
  544. * @param string $arg1, $arg2 ... $argN strings that will be concatinated.
  545. * @return string
  546. */
  547. public function getConcatExpression()
  548. {
  549. return join(' || ' , func_get_args());
  550. }
  551. /**
  552. * Returns the SQL for a logical not.
  553. *
  554. * Example:
  555. * <code>
  556. * $q = new Doctrine_Query();
  557. * $e = $q->expr;
  558. * $q->select('*')->from('table')
  559. * ->where($e->eq('id', $e->not('null'));
  560. * </code>
  561. *
  562. * @return string a logical expression
  563. */
  564. public function getNotExpression($expression)
  565. {
  566. return 'NOT(' . $expression . ')';
  567. }
  568. /**
  569. * Returns the SQL to check if a value is one in a set of
  570. * given values.
  571. *
  572. * in() accepts an arbitrary number of parameters. The first parameter
  573. * must always specify the value that should be matched against. Successive
  574. * must contain a logical expression or an array with logical expressions.
  575. * These expressions will be matched against the first parameter.
  576. *
  577. * @param string $column the value that should be matched against
  578. * @param string|array(string) values that will be matched against $column
  579. * @return string logical expression
  580. */
  581. public function getInExpression($column, $values)
  582. {
  583. if ( ! is_array($values)) {
  584. $values = array($values);
  585. }
  586. $values = $this->getIdentifiers($values);
  587. if (count($values) == 0) {
  588. throw \InvalidArgumentException('Values must not be empty.');
  589. }
  590. return $column . ' IN (' . implode(', ', $values) . ')';
  591. }
  592. /**
  593. * Returns SQL that checks if a expression is null.
  594. *
  595. * @param string $expression the expression that should be compared to null
  596. * @return string logical expression
  597. */
  598. public function getIsNullExpression($expression)
  599. {
  600. return $expression . ' IS NULL';
  601. }
  602. /**
  603. * Returns SQL that checks if a expression is not null.
  604. *
  605. * @param string $expression the expression that should be compared to null
  606. * @return string logical expression
  607. */
  608. public function getIsNotNullExpression($expression)
  609. {
  610. return $expression . ' IS NOT NULL';
  611. }
  612. /**
  613. * Returns SQL that checks if an expression evaluates to a value between
  614. * two values.
  615. *
  616. * The parameter $expression is checked if it is between $value1 and $value2.
  617. *
  618. * Note: There is a slight difference in the way BETWEEN works on some databases.
  619. * http://www.w3schools.com/sql/sql_between.asp. If you want complete database
  620. * independence you should avoid using between().
  621. *
  622. * @param string $expression the value to compare to
  623. * @param string $value1 the lower value to compare with
  624. * @param string $value2 the higher value to compare with
  625. * @return string logical expression
  626. */
  627. public function getBetweenExpression($expression, $value1, $value2)
  628. {
  629. return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2;
  630. }
  631. public function getAcosExpression($value)
  632. {
  633. return 'ACOS(' . $value . ')';
  634. }
  635. public function getSinExpression($value)
  636. {
  637. return 'SIN(' . $value . ')';
  638. }
  639. public function getPiExpression()
  640. {
  641. return 'PI()';
  642. }
  643. public function getCosExpression($value)
  644. {
  645. return 'COS(' . $value . ')';
  646. }
  647. /**
  648. * Calculate the difference in days between the two passed dates.
  649. *
  650. * Computes diff = date1 - date2
  651. *
  652. * @param string $date1
  653. * @param string $date2
  654. * @return string
  655. */
  656. public function getDateDiffExpression($date1, $date2)
  657. {
  658. throw DBALException::notSupported(__METHOD__);
  659. }
  660. /**
  661. * Add the number of given days to a date.
  662. *
  663. * @param string $date
  664. * @param int $days
  665. * @return string
  666. */
  667. public function getDateAddDaysExpression($date, $days)
  668. {
  669. throw DBALException::notSupported(__METHOD__);
  670. }
  671. /**
  672. * Substract the number of given days to a date.
  673. *
  674. * @param string $date
  675. * @param int $days
  676. * @return string
  677. */
  678. public function getDateSubDaysExpression($date, $days)
  679. {
  680. throw DBALException::notSupported(__METHOD__);
  681. }
  682. /**
  683. * Add the number of given months to a date.
  684. *
  685. * @param string $date
  686. * @param int $months
  687. * @return string
  688. */
  689. public function getDateAddMonthExpression($date, $months)
  690. {
  691. throw DBALException::notSupported(__METHOD__);
  692. }
  693. /**
  694. * Substract the number of given months to a date.
  695. *
  696. * @param string $date
  697. * @param int $months
  698. * @return string
  699. */
  700. public function getDateSubMonthExpression($date, $months)
  701. {
  702. throw DBALException::notSupported(__METHOD__);
  703. }
  704. public function getForUpdateSQL()
  705. {
  706. return 'FOR UPDATE';
  707. }
  708. /**
  709. * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification.
  710. *
  711. * @param string $fromClause
  712. * @param int $lockMode
  713. * @return string
  714. */
  715. public function appendLockHint($fromClause, $lockMode)
  716. {
  717. return $fromClause;
  718. }
  719. /**
  720. * Get the sql snippet to append to any SELECT statement which locks rows in shared read lock.
  721. *
  722. * This defaults to the ASNI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database
  723. * vendors allow to lighten this constraint up to be a real read lock.
  724. *
  725. * @return string
  726. */
  727. public function getReadLockSQL()
  728. {
  729. return $this->getForUpdateSQL();
  730. }
  731. /**
  732. * Get the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows.
  733. *
  734. * The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ASNI SQL standard.
  735. *
  736. * @return string
  737. */
  738. public function getWriteLockSQL()
  739. {
  740. return $this->getForUpdateSQL();
  741. }
  742. public function getDropDatabaseSQL($database)
  743. {
  744. return 'DROP DATABASE ' . $database;
  745. }
  746. /**
  747. * Drop a Table
  748. *
  749. * @throws \InvalidArgumentException
  750. * @param Table|string $table
  751. * @return string
  752. */
  753. public function getDropTableSQL($table)
  754. {
  755. if ($table instanceof \Doctrine\DBAL\Schema\Table) {
  756. $table = $table->getQuotedName($this);
  757. } else if(!is_string($table)) {
  758. throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
  759. }
  760. return 'DROP TABLE ' . $table;
  761. }
  762. /**
  763. * Get SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction.
  764. *
  765. * @param Table|string $table
  766. * @return string
  767. */
  768. public function getDropTemporaryTableSQL($table)
  769. {
  770. return $this->getDropTableSQL($table);
  771. }
  772. /**
  773. * Drop index from a table
  774. *
  775. * @param Index|string $name
  776. * @param string|Table $table
  777. * @return string
  778. */
  779. public function getDropIndexSQL($index, $table=null)
  780. {
  781. if($index instanceof \Doctrine\DBAL\Schema\Index) {
  782. $index = $index->getQuotedName($this);
  783. } else if(!is_string($index)) {
  784. throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
  785. }
  786. return 'DROP INDEX ' . $index;
  787. }
  788. /**
  789. * Get drop constraint sql
  790. *
  791. * @param \Doctrine\DBAL\Schema\Constraint $constraint
  792. * @param string|Table $table
  793. * @return string
  794. */
  795. public function getDropConstraintSQL($constraint, $table)
  796. {
  797. if ($constraint instanceof \Doctrine\DBAL\Schema\Constraint) {
  798. $constraint = $constraint->getQuotedName($this);
  799. }
  800. if ($table instanceof \Doctrine\DBAL\Schema\Table) {
  801. $table = $table->getQuotedName($this);
  802. }
  803. return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint;
  804. }
  805. /**
  806. * @param ForeignKeyConstraint|string $foreignKey
  807. * @param Table|string $table
  808. * @return string
  809. */
  810. public function getDropForeignKeySQL($foreignKey, $table)
  811. {
  812. if ($foreignKey instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
  813. $foreignKey = $foreignKey->getQuotedName($this);
  814. }
  815. if ($table instanceof \Doctrine\DBAL\Schema\Table) {
  816. $table = $table->getQuotedName($this);
  817. }
  818. return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey;
  819. }
  820. /**
  821. * Gets the SQL statement(s) to create a table with the specified name, columns and constraints
  822. * on this platform.
  823. *
  824. * @param string $table The name of the table.
  825. * @param int $createFlags
  826. * @return array The sequence of SQL statements.
  827. */
  828. public function getCreateTableSQL(Table $table, $createFlags=self::CREATE_INDEXES)
  829. {
  830. if ( ! is_int($createFlags)) {
  831. throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer.");
  832. }
  833. if (count($table->getColumns()) == 0) {
  834. throw DBALException::noColumnsSpecifiedForTable($table->getName());
  835. }
  836. $tableName = $table->getQuotedName($this);
  837. $options = $table->getOptions();
  838. $options['uniqueConstraints'] = array();
  839. $options['indexes'] = array();
  840. $options['primary'] = array();
  841. if (($createFlags&self::CREATE_INDEXES) > 0) {
  842. foreach ($table->getIndexes() AS $index) {
  843. /* @var $index Index */
  844. if ($index->isPrimary()) {
  845. $options['primary'] = $index->getColumns();
  846. } else {
  847. $options['indexes'][$index->getName()] = $index;
  848. }
  849. }
  850. }
  851. $columns = array();
  852. foreach ($table->getColumns() AS $column) {
  853. /* @var \Doctrine\DBAL\Schema\Column $column */
  854. $columnData = array();
  855. $columnData['name'] = $column->getQuotedName($this);
  856. $columnData['type'] = $column->getType();
  857. $columnData['length'] = $column->getLength();
  858. $columnData['notnull'] = $column->getNotNull();
  859. $columnData['fixed'] = $column->getFixed();
  860. $columnData['unique'] = false; // TODO: what do we do about this?
  861. $columnData['version'] = ($column->hasPlatformOption("version"))?$column->getPlatformOption('version'):false;
  862. if(strtolower($columnData['type']) == "string" && $columnData['length'] === null) {
  863. $columnData['length'] = 255;
  864. }
  865. $columnData['unsigned'] = $column->getUnsigned();
  866. $columnData['precision'] = $column->getPrecision();
  867. $columnData['scale'] = $column->getScale();
  868. $columnData['default'] = $column->getDefault();
  869. $columnData['columnDefinition'] = $column->getColumnDefinition();
  870. $columnData['autoincrement'] = $column->getAutoincrement();
  871. $columnData['comment'] = $this->getColumnComment($column);
  872. if(in_array($column->getName(), $options['primary'])) {
  873. $columnData['primary'] = true;
  874. }
  875. $columns[$columnData['name']] = $columnData;
  876. }
  877. if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) {
  878. $options['foreignKeys'] = array();
  879. foreach ($table->getForeignKeys() AS $fkConstraint) {
  880. $options['foreignKeys'][] = $fkConstraint;
  881. }
  882. }
  883. $sql = $this->_getCreateTableSQL($tableName, $columns, $options);
  884. if ($this->supportsCommentOnStatement()) {
  885. foreach ($table->getColumns() AS $column) {
  886. if ($this->getColumnComment($column)) {
  887. $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getName(), $this->getColumnComment($column));
  888. }
  889. }
  890. }
  891. return $sql;
  892. }
  893. public function getCommentOnColumnSQL($tableName, $columnName, $comment)
  894. {
  895. return "COMMENT ON COLUMN " . $tableName . "." . $columnName . " IS '" . $comment . "'";
  896. }
  897. /**
  898. * @param string $tableName
  899. * @param array $columns
  900. * @param array $options
  901. * @return array
  902. */
  903. protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
  904. {
  905. $columnListSql = $this->getColumnDeclarationListSQL($columns);
  906. if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
  907. foreach ($options['uniqueConstraints'] as $name => $definition) {
  908. $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
  909. }
  910. }
  911. if (isset($options['primary']) && ! empty($options['primary'])) {
  912. $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
  913. }
  914. if (isset($options['indexes']) && ! empty($options['indexes'])) {
  915. foreach($options['indexes'] as $index => $definition) {
  916. $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
  917. }
  918. }
  919. $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
  920. $check = $this->getCheckDeclarationSQL($columns);
  921. if ( ! empty($check)) {
  922. $query .= ', ' . $check;
  923. }
  924. $query .= ')';
  925. $sql[] = $query;
  926. if (isset($options['foreignKeys'])) {
  927. foreach ((array) $options['foreignKeys'] AS $definition) {
  928. $sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
  929. }
  930. }
  931. return $sql;
  932. }
  933. public function getCreateTemporaryTableSnippetSQL()
  934. {
  935. return "CREATE TEMPORARY TABLE";
  936. }
  937. /**
  938. * Gets the SQL to create a sequence on this platform.
  939. *
  940. * @param \Doctrine\DBAL\Schema\Sequence $sequence
  941. * @throws DBALException
  942. */
  943. public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
  944. {
  945. throw DBALException::notSupported(__METHOD__);
  946. }
  947. /**
  948. * Gets the SQL statement to change a sequence on this platform.
  949. *
  950. * @param \Doctrine\DBAL\Schema\Sequence $sequence
  951. * @return string
  952. */
  953. public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
  954. {
  955. throw DBALException::notSupported(__METHOD__);
  956. }
  957. /**
  958. * Gets the SQL to create a constraint on a table on this platform.
  959. *
  960. * @param Constraint $constraint
  961. * @param string|Table $table
  962. * @return string
  963. */
  964. public function getCreateConstraintSQL(\Doctrine\DBAL\Schema\Constraint $constraint, $table)
  965. {
  966. if ($table instanceof \Doctrine\DBAL\Schema\Table) {
  967. $table = $table->getQuotedName($this);
  968. }
  969. $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this);
  970. $columns = array();
  971. foreach ($constraint->getColumns() as $column) {
  972. $columns[] = $column;
  973. }
  974. $columnList = '('. implode(', ', $columns) . ')';
  975. $referencesClause = '';
  976. if ($constraint instanceof \Doctrine\DBAL\Schema\Index) {
  977. if($constraint->isPrimary()) {
  978. $query .= ' PRIMARY KEY';
  979. } elseif ($constraint->isUnique()) {
  980. $query .= ' UNIQUE';
  981. } else {
  982. throw new \InvalidArgumentException(
  983. 'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().'
  984. );
  985. }
  986. } else if ($constraint instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
  987. $query .= ' FOREIGN KEY';
  988. $foreignColumns = array();
  989. foreach ($constraint->getForeignColumns() AS $column) {
  990. $foreignColumns[] = $column;
  991. }
  992. $referencesClause = ' REFERENCES '.$constraint->getForeignTableName(). ' ('.implode(', ', $foreignColumns).')';
  993. }
  994. $query .= ' '.$columnList.$referencesClause;
  995. return $query;
  996. }
  997. /**
  998. * Gets the SQL to create an index on a table on this platform.
  999. *
  1000. * @param Index $index
  1001. * @param string|Table $table name of the table on which the index is to be created
  1002. * @return string
  1003. */
  1004. public function getCreateIndexSQL(Index $index, $table)
  1005. {
  1006. if ($table instanceof Table) {
  1007. $table = $table->getQuotedName($this);
  1008. }
  1009. $name = $index->getQuotedName($this);
  1010. $columns = $index->getColumns();
  1011. if (count($columns) == 0) {
  1012. throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
  1013. }
  1014. if ($index->isPrimary()) {
  1015. return $this->getCreatePrimaryKeySQL($index, $table);
  1016. } else {
  1017. $type = '';
  1018. if ($index->isUnique()) {
  1019. $type = 'UNIQUE ';
  1020. }
  1021. $query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table;
  1022. $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')';
  1023. }
  1024. return $query;
  1025. }
  1026. /**
  1027. * Get SQL to create an unnamed primary key constraint.
  1028. *
  1029. * @param Index $index
  1030. * @param string|Table $table
  1031. * @return string
  1032. */
  1033. public function getCreatePrimaryKeySQL(Index $index, $table)
  1034. {
  1035. return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getColumns()) . ')';
  1036. }
  1037. /**
  1038. * Quotes a string so that it can be safely used as a table or column name,
  1039. * even if it is a reserved word of the platform.
  1040. *
  1041. * NOTE: Just because you CAN use quoted identifiers doesn't mean
  1042. * you SHOULD use them. In general, they end up causing way more
  1043. * problems than they solve.
  1044. *
  1045. * @param string $str identifier name to be quoted
  1046. * @return string quoted identifier string
  1047. */
  1048. public function quoteIdentifier($str)
  1049. {
  1050. $c = $this->getIdentifierQuoteCharacter();
  1051. return $c . str_replace($c, $c.$c, $str) . $c;
  1052. }
  1053. /**
  1054. * Create a new foreign key
  1055. *
  1056. * @param ForeignKeyConstraint $foreignKey ForeignKey instance
  1057. * @param string|Table $table name of the table on which the foreign key is to be created
  1058. * @return string
  1059. */
  1060. public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
  1061. {
  1062. if ($table instanceof \Doctrine\DBAL\Schema\Table) {
  1063. $table = $table->getQuotedName($this);
  1064. }
  1065. $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey);
  1066. return $query;
  1067. }
  1068. /**
  1069. * Gets the sql statements for altering an existing table.
  1070. *
  1071. * The method returns an array of sql statements, since some platforms need several statements.
  1072. *
  1073. * @param TableDiff $diff
  1074. * @return array
  1075. */
  1076. public function getAlterTableSQL(TableDiff $diff)
  1077. {
  1078. throw DBALException::notSupported(__METHOD__);
  1079. }
  1080. protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff)
  1081. {
  1082. $tableName = $diff->name;
  1083. $sql = array();
  1084. if ($this->supportsForeignKeyConstraints()) {
  1085. foreach ($diff->removedForeignKeys AS $foreignKey) {
  1086. $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
  1087. }
  1088. foreach ($diff->changedForeignKeys AS $foreignKey) {
  1089. $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
  1090. }
  1091. }
  1092. foreach ($diff->removedIndexes AS $index) {
  1093. $sql[] = $this->getDropIndexSQL($index, $tableName);
  1094. }
  1095. foreach ($diff->changedIndexes AS $index) {
  1096. $sql[] = $this->getDropIndexSQL($index, $tableName);
  1097. }
  1098. return $sql;
  1099. }
  1100. protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
  1101. {
  1102. if ($diff->newName !== false) {
  1103. $tableName = $diff->newName;
  1104. } else {
  1105. $tableName = $diff->name;
  1106. }
  1107. $sql = array();
  1108. if ($this->supportsForeignKeyConstraints()) {
  1109. foreach ($diff->addedForeignKeys AS $foreignKey) {
  1110. $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
  1111. }
  1112. foreach ($diff->changedForeignKeys AS $foreignKey) {
  1113. $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
  1114. }
  1115. }
  1116. foreach ($diff->addedIndexes AS $index) {
  1117. $sql[] = $this->getCreateIndexSQL($index, $tableName);
  1118. }
  1119. foreach ($diff->changedIndexes AS $index) {
  1120. $sql[] = $this->getCreateIndexSQL($index, $tableName);
  1121. }
  1122. return $sql;
  1123. }
  1124. /**
  1125. * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions.
  1126. *
  1127. * @param TableDiff $diff
  1128. * @return array
  1129. */
  1130. protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff)
  1131. {
  1132. return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff));
  1133. }
  1134. /**
  1135. * Get declaration of a number of fields in bulk
  1136. *
  1137. * @param array $fields a multidimensional associative array.
  1138. * The first dimension determines the field name, while the second
  1139. * dimension is keyed with the name of the properties
  1140. * of the field being declared as array indexes. Currently, the types
  1141. * of supported field properties are as follows:
  1142. *
  1143. * length
  1144. * Integer value that determines the maximum length of the text
  1145. * field. If this argument is missing the field should be
  1146. * declared to have the longest length allowed by the DBMS.
  1147. *
  1148. * default
  1149. * Text value to be used as default for this field.
  1150. *
  1151. * notnull
  1152. * Boolean flag that indicates whether this field is constrained
  1153. * to not be set to null.
  1154. * charset
  1155. * Text value with the default CHARACTER SET for this field.
  1156. * collation
  1157. * Text value with the default COLLATION for this field.
  1158. * unique
  1159. * unique constraint
  1160. *
  1161. * @return string
  1162. */
  1163. public function getColumnDeclarationListSQL(array $fields)
  1164. {
  1165. $queryFields = array();
  1166. foreach ($fields as $fieldName => $field) {
  1167. $query = $this->getColumnDeclarationSQL($fieldName, $field);
  1168. $queryFields[] = $query;
  1169. }
  1170. return implode(', ', $queryFields);
  1171. }
  1172. /**
  1173. * Obtain DBMS specific SQL code portion needed to declare a generic type
  1174. * field to be used in statements like CREATE TABLE.
  1175. *
  1176. * @param string $name name the field to be declared.
  1177. * @param array $field associative array with the name of the properties
  1178. * of the field being declared as array indexes. Currently, the types
  1179. * of supported field properties are as follows:
  1180. *
  1181. * length
  1182. * Integer value that determines the maximum length of the text
  1183. * field. If this argument is missing the field should be
  1184. * declared to have the longest length allowed by the DBMS.
  1185. *
  1186. * default
  1187. * Text value to be used as default for this field.
  1188. *
  1189. * notnull
  1190. * Boolean flag that indicates whether this field is constrained
  1191. * to not be set to null.
  1192. * charset
  1193. * Text value with the default CHARACTER SET for this field.
  1194. * collation
  1195. * Text value with the default COLLATION for this field.
  1196. * unique
  1197. * unique constraint
  1198. * check
  1199. * column check constraint
  1200. * columnDefinition
  1201. * a string that defines the complete column
  1202. *
  1203. * @return string DBMS specific SQL code portion that should be used to declare the column.
  1204. */
  1205. public function getColumnDeclarationSQL($name, array $field)
  1206. {
  1207. if (isset($field['columnDefinition'])) {
  1208. $columnDef = $this->getCustomTypeDeclarationSQL($field);
  1209. } else {
  1210. $default = $this->getDefaultValueDeclarationSQL($field);
  1211. $charset = (isset($field['charset']) && $field['charset']) ?
  1212. ' ' . $this->getColumnCharsetDeclarationSQL($field['charset']) : '';
  1213. $collation = (isset($field['collation']) && $field['collation']) ?
  1214. ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : '';
  1215. $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
  1216. $unique = (isset($field['unique']) && $field['unique']) ?
  1217. ' ' . $this->getUniqueFieldDeclarationSQL() : '';
  1218. $check = (isset($field['check']) && $field['check']) ?
  1219. ' ' . $field['check'] : '';
  1220. $typeDecl = $field['type']->getSqlDeclaration($field, $this);
  1221. $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
  1222. }
  1223. if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment']) {
  1224. $columnDef .= " COMMENT '" . $field['comment'] . "'";
  1225. }
  1226. return $name . ' ' . $columnDef;
  1227. }
  1228. /**
  1229. * Gets the SQL snippet that declares a floating point column of arbitrary precision.
  1230. *
  1231. * @param array $columnDef
  1232. * @return string
  1233. */
  1234. public function getDecimalTypeDeclarationSQL(array $columnDef)
  1235. {
  1236. $columnDef['precision'] = ( ! isset($columnDef['precision']) || empty($columnDef['precision']))
  1237. ? 10 : $columnDef['precision'];
  1238. $columnDef['scale'] = ( ! isset($columnDef['scale']) || empty($columnDef['scale']))
  1239. ? 0 : $columnDef['scale'];
  1240. return 'NUMERIC(' . $columnDef['precision'] . ', ' . $columnDef['scale'] . ')';
  1241. }
  1242. /**
  1243. * Obtain DBMS specific SQL code portion needed to set a default value
  1244. * declaration to be used in statements like CREATE TABLE.
  1245. *
  1246. * @param array $field field definition array
  1247. * @return string DBMS specific SQL code portion needed to set a default value
  1248. */
  1249. public function getDefaultValueDeclarationSQL($field)
  1250. {
  1251. $default = empty($field['notnull']) ? ' DEFAULT NULL' : '';
  1252. if (isset($field['default'])) {
  1253. $default = " DEFAULT '".$field['default']."'";
  1254. if (isset($field['type'])) {
  1255. if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) {
  1256. $default = " DEFAULT ".$field['default'];
  1257. } else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) {
  1258. $default = " DEFAULT ".$this->getCurrentTimestampSQL();
  1259. }
  1260. }
  1261. }
  1262. return $default;
  1263. }
  1264. /**
  1265. * Obtain DBMS specific SQL code portion needed to set a CHECK constraint
  1266. * declaration to be used in statements like CREATE TABLE.
  1267. *
  1268. * @param array $definition check definition
  1269. * @return string DBMS specific SQL code portion needed to set a CHECK constraint
  1270. */
  1271. public function getCheckDeclarationSQL(array $definition)
  1272. {
  1273. $constraints = array();
  1274. foreach ($definition as $field => $def) {
  1275. if (is_string($def)) {
  1276. $constraints[] = 'CHECK (' . $def . ')';
  1277. } else {
  1278. if (isset($def['min'])) {
  1279. $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')';
  1280. }
  1281. if (isset($def['max'])) {
  1282. $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')';
  1283. }
  1284. }
  1285. }
  1286. return implode(', ', $constraints);
  1287. }
  1288. /**
  1289. * Obtain DBMS specific SQL code portion needed to set a unique
  1290. * constraint declaration to be used in statements like CREATE TABLE.
  1291. *
  1292. * @param string $name name of the unique constraint
  1293. * @param Index $index index definition
  1294. * @return string DBMS specific SQL code portion needed
  1295. * to set a constraint
  1296. */
  1297. public function getUniqueConstraintDeclarationSQL($name, Index $index)
  1298. {
  1299. if (count($index->getColumns()) == 0) {
  1300. throw \InvalidArgumentException("Incomplete definition. 'columns' required.");
  1301. }
  1302. return 'CONSTRAINT ' . $name . ' UNIQUE ('
  1303. . $this->getIndexFieldDeclarationListSQL($index->getColumns())
  1304. . ')';
  1305. }
  1306. /**
  1307. * Obtain DBMS specific SQL code portion needed to set an index
  1308. * declaration to be used in statements like CREATE TABLE.
  1309. *
  1310. * @param string $name name of the index
  1311. * @param Index $index index definition
  1312. * @return string DBMS specific SQL code portion needed to set an index
  1313. */
  1314. public function getIndexDeclarationSQL($name, Index $index)
  1315. {
  1316. $type = '';
  1317. if($index->isUnique()) {
  1318. $type = 'UNIQUE ';
  1319. }
  1320. if (count($index->getColumns()) == 0) {
  1321. throw \InvalidArgumentException("Incomplete definition. 'columns' required.");
  1322. }
  1323. return $type . 'INDEX ' . $name . ' ('
  1324. . $this->getIndexFieldDeclarationListSQL($index->getColumns())
  1325. . ')';
  1326. }
  1327. /**
  1328. * getCustomTypeDeclarationSql
  1329. * Obtail SQL code portion needed to create a custom column,
  1330. * e.g. when a field has the "columnDefinition" keyword.
  1331. * Only "AUTOINCREMENT" and "PRIMARY KEY" are added if appropriate.
  1332. *
  1333. * @return string
  1334. */
  1335. public function getCustomTypeDeclarationSQL(array $columnDef)
  1336. {
  1337. return $columnDef['columnDefinition'];
  1338. }
  1339. /**
  1340. * getIndexFieldDeclarationList
  1341. * Obtain DBMS specific SQL code portion needed to set an index
  1342. * declaration to be used in statements like CREATE TABLE.
  1343. *
  1344. * @return string
  1345. */
  1346. public function getIndexFieldDeclarationListSQL(array $fields)
  1347. {
  1348. $ret = array();
  1349. foreach ($fields as $field => $definition) {
  1350. if (is_array($definition)) {
  1351. $ret[] = $field;
  1352. } else {
  1353. $ret[] = $definition;
  1354. }
  1355. }
  1356. return implode(', ', $ret);
  1357. }
  1358. /**
  1359. * A method to return the required SQL string that fits between CREATE ... TABLE
  1360. * to create the table as a temporary table.
  1361. *
  1362. * Should be overridden in driver classes to return the correct string for the
  1363. * specific database type.
  1364. *
  1365. * The default is to return the string "TEMPORARY" - this will result in a
  1366. * SQL error for any database that does not support temporary tables, or that
  1367. * requires a different SQL command from "CREATE TEMPORARY TABLE".
  1368. *
  1369. * @return string The string required to be placed between "CREATE" and "TABLE"
  1370. * to generate a temporary table, if possible.
  1371. */
  1372. public function getTemporaryTableSQL()
  1373. {
  1374. return 'TEMPORARY';
  1375. }
  1376. /**
  1377. * Some vendors require temporary table names to be qualified specially.
  1378. *
  1379. * @param string $tableName
  1380. * @return string
  1381. */
  1382. public function getTemporaryTableName($tableName)
  1383. {
  1384. return $tableName;
  1385. }
  1386. /**
  1387. * Get sql query to show a list of database.
  1388. *
  1389. * @return string
  1390. */
  1391. public function getShowDatabasesSQL()
  1392. {
  1393. throw DBALException::notSupported(__METHOD__);
  1394. }
  1395. /**
  1396. * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
  1397. * of a field declaration to be used in statements like CREATE TABLE.
  1398. *
  1399. * @param array $definition an associative array with the following structure:
  1400. * name optional constraint name
  1401. *
  1402. * local the local field(s)
  1403. *
  1404. * foreign the foreign reference field(s)
  1405. *
  1406. * foreignTable the name of the foreign table
  1407. *
  1408. * onDelete referential delete action
  1409. *
  1410. * onUpdate referential update action
  1411. *
  1412. * deferred deferred constraint checking
  1413. *
  1414. * The onDelete and onUpdate keys accept the following values:
  1415. *
  1416. * CASCADE: Delete or update the row from the parent table and automatically delete or
  1417. * update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
  1418. * Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column
  1419. * in the parent table or in the child table.
  1420. *
  1421. * SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the
  1422. * child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier
  1423. * specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
  1424. *
  1425. * NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary
  1426. * key value is not allowed to proceed if there is a related foreign key value in the referenced table.
  1427. *
  1428. * RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as
  1429. * omitting the ON DELETE or ON UPDATE clause.
  1430. *
  1431. * SET DEFAULT
  1432. *
  1433. * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
  1434. * of a field declaration.
  1435. */
  1436. public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey)
  1437. {
  1438. $sql = $this->getForeignKeyBaseDeclarationSQL($foreignKey);
  1439. $sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey);
  1440. return $sql;
  1441. }
  1442. /**
  1443. * Return the FOREIGN KEY query section dealing with non-standard options
  1444. * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
  1445. *
  1446. * @param ForeignKeyConstraint $foreignKey foreign key definition
  1447. * @return string
  1448. */
  1449. public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
  1450. {
  1451. $query = '';
  1452. if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) {
  1453. $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate'));
  1454. }
  1455. if ($foreignKey->hasOption('onDelete')) {
  1456. $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
  1457. }
  1458. return $query;
  1459. }
  1460. /**
  1461. * returns given referential action in uppercase if valid, otherwise throws
  1462. * an exception
  1463. *
  1464. * @throws Doctrine_Exception_Exception if unknown referential action given
  1465. * @param string $action foreign key referential action
  1466. * @param string foreign key referential action in uppercase
  1467. */
  1468. public function getForeignKeyReferentialActionSQL($action)
  1469. {
  1470. $upper = strtoupper($action);
  1471. switch ($upper) {
  1472. case 'CASCADE':
  1473. case 'SET NULL':
  1474. case 'NO ACTION':
  1475. case 'RESTRICT':
  1476. case 'SET DEFAULT':
  1477. return $upper;
  1478. break;
  1479. default:
  1480. throw new \InvalidArgumentException('Invalid foreign key action: ' . $upper);
  1481. }
  1482. }
  1483. /**
  1484. * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
  1485. * of a field declaration to be used in statements like CREATE TABLE.
  1486. *
  1487. * @param ForeignKeyConstraint $foreignKey
  1488. * @return string
  1489. */
  1490. public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey)
  1491. {
  1492. $sql = '';
  1493. if (strlen($foreignKey->getName())) {
  1494. $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' ';
  1495. }
  1496. $sql .= 'FOREIGN KEY (';
  1497. if (count($foreignKey->getLocalColumns()) == 0) {
  1498. throw new \InvalidArgumentException("Incomplete definition. 'local' required.");
  1499. }
  1500. if (count($foreignKey->getForeignColumns()) == 0) {
  1501. throw new \InvalidArgumentException("Incomplete definition. 'foreign' required.");
  1502. }
  1503. if (strlen($foreignKey->getForeignTableName()) == 0) {
  1504. throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required.");
  1505. }
  1506. $sql .= implode(', ', $foreignKey->getLocalColumns())
  1507. . ') REFERENCES '
  1508. . $foreignKey->getForeignTableName() . '('
  1509. . implode(', ', $foreignKey->getForeignColumns()) . ')';
  1510. return $sql;
  1511. }
  1512. /**
  1513. * Obtain DBMS specific SQL code portion needed to set the UNIQUE constraint
  1514. * of a field declaration to be used in statements like CREATE TABLE.
  1515. *
  1516. * @return string DBMS specific SQL code portion needed to set the UNIQUE constraint
  1517. * of a field declaration.
  1518. */
  1519. public function getUniqueFieldDeclarationSQL()
  1520. {
  1521. return 'UNIQUE';
  1522. }
  1523. /**
  1524. * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
  1525. * of a field declaration to be used in statements like CREATE TABLE.
  1526. *
  1527. * @param string $charset name of the charset
  1528. * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
  1529. * of a field declaration.
  1530. */
  1531. public function getColumnCharsetDeclarationSQL($charset)
  1532. {
  1533. return '';
  1534. }
  1535. /**
  1536. * Obtain DBMS specific SQL code portion needed to set the COLLATION
  1537. * of a field declaration to be used in statements like CREATE TABLE.
  1538. *
  1539. * @param string $collation name of the collation
  1540. * @return string DBMS specific SQL code portion needed to set the COLLATION
  1541. * of a field declaration.
  1542. */
  1543. public function getColumnCollationDeclarationSQL($collation)
  1544. {
  1545. return '';
  1546. }
  1547. /**
  1548. * Whether the platform prefers sequences for ID generation.
  1549. * Subclasses should override this method to return TRUE if they prefer sequences.
  1550. *
  1551. * @return boolean
  1552. */
  1553. public function prefersSequences()
  1554. {
  1555. return false;
  1556. }
  1557. /**
  1558. * Whether the platform prefers identity columns (eg. autoincrement) for ID generation.
  1559. * Subclasses should override this method to return TRUE if they prefer identity columns.
  1560. *
  1561. * @return boolean
  1562. */
  1563. public function prefersIdentityColumns()
  1564. {
  1565. return false;
  1566. }
  1567. /**
  1568. * Some platforms need the boolean values to be converted.
  1569. *
  1570. * The default conversion in this implementation converts to integers (false => 0, true => 1).
  1571. *
  1572. * @param mixed $item
  1573. */
  1574. public function convertBooleans($item)
  1575. {
  1576. if (is_array($item)) {
  1577. foreach ($item as $k => $value) {
  1578. if (is_bool($value)) {
  1579. $item[$k] = (int) $value;
  1580. }
  1581. }
  1582. } else if (is_bool($item)) {
  1583. $item = (int) $item;
  1584. }
  1585. return $item;
  1586. }
  1587. /**
  1588. * Gets the SQL statement specific for the platform to set the charset.
  1589. *
  1590. * This function is MySQL specific and required by
  1591. * {@see \Doctrine\DBAL\Connection::setCharset($charset)}
  1592. *
  1593. * @param string $charset
  1594. * @return string
  1595. */
  1596. public function getSetCharsetSQL($charset)
  1597. {
  1598. return "SET NAMES '".$charset."'";
  1599. }
  1600. /**
  1601. * Gets the SQL specific for the platform to get the current date.
  1602. *
  1603. * @return string
  1604. */
  1605. public function getCurrentDateSQL()
  1606. {
  1607. return 'CURRENT_DATE';
  1608. }
  1609. /**
  1610. * Gets the SQL specific for the platform to get the current time.
  1611. *
  1612. * @return string
  1613. */
  1614. public function getCurrentTimeSQL()
  1615. {
  1616. return 'CURRENT_TIME';
  1617. }
  1618. /**
  1619. * Gets the SQL specific for the platform to get the current timestamp
  1620. *
  1621. * @return string
  1622. */
  1623. public function getCurrentTimestampSQL()
  1624. {
  1625. return 'CURRENT_TIMESTAMP';
  1626. }
  1627. /**
  1628. * Get sql for transaction isolation level Connection constant
  1629. *
  1630. * @param integer $level
  1631. */
  1632. protected function _getTransactionIsolationLevelSQL($level)
  1633. {
  1634. switch ($level) {
  1635. case Connection::TRANSACTION_READ_UNCOMMITTED:
  1636. return 'READ UNCOMMITTED';
  1637. case Connection::TRANSACTION_READ_COMMITTED:
  1638. return 'READ COMMITTED';
  1639. case Connection::TRANSACTION_REPEATABLE_READ:
  1640. return 'REPEATABLE READ';
  1641. case Connection::TRANSACTION_SERIALIZABLE:
  1642. return 'SERIALIZABLE';
  1643. default:
  1644. throw new \InvalidArgumentException('Invalid isolation level:' . $level);
  1645. }
  1646. }
  1647. public function getListDatabasesSQL()
  1648. {
  1649. throw DBALException::notSupported(__METHOD__);
  1650. }
  1651. public function getListSequencesSQL($database)
  1652. {
  1653. throw DBALException::notSupported(__METHOD__);
  1654. }
  1655. public function getListTableConstraintsSQL($table)
  1656. {
  1657. throw DBALException::notSupported(__METHOD__);
  1658. }
  1659. public function getListTableColumnsSQL($table, $database = null)
  1660. {
  1661. throw DBALException::notSupported(__METHOD__);
  1662. }
  1663. public function getListTablesSQL()
  1664. {
  1665. throw DBALException::notSupported(__METHOD__);
  1666. }
  1667. public function getListUsersSQL()
  1668. {
  1669. throw DBALException::notSupported(__METHOD__);
  1670. }
  1671. /**
  1672. * Get the SQL to list all views of a database or user.
  1673. *
  1674. * @param string $database
  1675. * @return string
  1676. */
  1677. public function getListViewsSQL($database)
  1678. {
  1679. throw DBALException::notSupported(__METHOD__);
  1680. }
  1681. /**
  1682. * Get the list of indexes for the current database.
  1683. *
  1684. * The current database parameter is optional but will always be passed
  1685. * when using the SchemaManager API and is the database the given table is in.
  1686. *
  1687. * Attention: Some platforms only support currentDatabase when they
  1688. * are connected with that database. Cross-database information schema
  1689. * requests may be impossible.
  1690. *
  1691. * @param string $table
  1692. * @param string $currentDatabase
  1693. */
  1694. public function getListTableIndexesSQL($table, $currentDatabase = null)
  1695. {
  1696. throw DBALException::notSupported(__METHOD__);
  1697. }
  1698. public function getListTableForeignKeysSQL($table)
  1699. {
  1700. throw DBALException::notSupported(__METHOD__);
  1701. }
  1702. public function getCreateViewSQL($name, $sql)
  1703. {
  1704. throw DBALException::notSupported(__METHOD__);
  1705. }
  1706. public function getDropViewSQL($name)
  1707. {
  1708. throw DBALException::notSupported(__METHOD__);
  1709. }
  1710. public function getDropSequenceSQL($sequence)
  1711. {
  1712. throw DBALException::notSupported(__METHOD__);
  1713. }
  1714. public function getSequenceNextValSQL($sequenceName)
  1715. {
  1716. throw DBALException::notSupported(__METHOD__);
  1717. }
  1718. public function getCreateDatabaseSQL($database)
  1719. {
  1720. throw DBALException::notSupported(__METHOD__);
  1721. }
  1722. /**
  1723. * Get sql to set the transaction isolation level
  1724. *
  1725. * @param integer $level
  1726. */
  1727. public function getSetTransactionIsolationSQL($level)
  1728. {
  1729. throw DBALException::notSupported(__METHOD__);
  1730. }
  1731. /**
  1732. * Obtain DBMS specific SQL to be used to create datetime fields in
  1733. * statements like CREATE TABLE
  1734. *
  1735. * @param array $fieldDeclaration
  1736. * @return string
  1737. */
  1738. public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
  1739. {
  1740. throw DBALException::notSupported(__METHOD__);
  1741. }
  1742. /**
  1743. * Obtain DBMS specific SQL to be used to create datetime with timezone offset fields.
  1744. *
  1745. * @param array $fieldDeclaration
  1746. */
  1747. public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
  1748. {
  1749. return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration);
  1750. }
  1751. /**
  1752. * Obtain DBMS specific SQL to be used to create date fields in statements
  1753. * like CREATE TABLE.
  1754. *
  1755. * @param array $fieldDeclaration
  1756. * @return string
  1757. */
  1758. public function getDateTypeDeclarationSQL(array $fieldDeclaration)
  1759. {
  1760. throw DBALException::notSupported(__METHOD__);
  1761. }
  1762. /**
  1763. * Obtain DBMS specific SQL to be used to create time fields in statements
  1764. * like CREATE TABLE.
  1765. *
  1766. * @param array $fieldDeclaration
  1767. * @return string
  1768. */
  1769. public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
  1770. {
  1771. throw DBALException::notSupported(__METHOD__);
  1772. }
  1773. public function getFloatDeclarationSQL(array $fieldDeclaration)
  1774. {
  1775. return 'DOUBLE PRECISION';
  1776. }
  1777. /**
  1778. * Gets the default transaction isolation level of the platform.
  1779. *
  1780. * @return integer The default isolation level.
  1781. * @see Doctrine\DBAL\Connection\TRANSACTION_* constants.
  1782. */
  1783. public function getDefaultTransactionIsolationLevel()
  1784. {
  1785. return Connection::TRANSACTION_READ_COMMITTED;
  1786. }
  1787. /* supports*() metods */
  1788. /**
  1789. * Whether the platform supports sequences.
  1790. *
  1791. * @return boolean
  1792. */
  1793. public function supportsSequences()
  1794. {
  1795. return false;
  1796. }
  1797. /**
  1798. * Whether the platform supports identity columns.
  1799. * Identity columns are columns that recieve an auto-generated value from the
  1800. * database on insert of a row.
  1801. *
  1802. * @return boolean
  1803. */
  1804. public function supportsIdentityColumns()
  1805. {
  1806. return false;
  1807. }
  1808. /**
  1809. * Whether the platform supports indexes.
  1810. *
  1811. * @return boolean
  1812. */
  1813. public function supportsIndexes()
  1814. {
  1815. return true;
  1816. }
  1817. public function supportsAlterTable()
  1818. {
  1819. return true;
  1820. }
  1821. /**
  1822. * Whether the platform supports transactions.
  1823. *
  1824. * @return boolean
  1825. */
  1826. public function supportsTransactions()
  1827. {
  1828. return true;
  1829. }
  1830. /**
  1831. * Whether the platform supports savepoints.
  1832. *
  1833. * @return boolean
  1834. */
  1835. public function supportsSavepoints()
  1836. {
  1837. return true;
  1838. }
  1839. /**
  1840. * Whether the platform supports releasing savepoints.
  1841. *
  1842. * @return boolean
  1843. */
  1844. public function supportsReleaseSavepoints()
  1845. {
  1846. return $this->supportsSavepoints();
  1847. }
  1848. /**
  1849. * Whether the platform supports primary key constraints.
  1850. *
  1851. * @return boolean
  1852. */
  1853. public function supportsPrimaryConstraints()
  1854. {
  1855. return true;
  1856. }
  1857. /**
  1858. * Does the platform supports foreign key constraints?
  1859. *
  1860. * @return boolean
  1861. */
  1862. public function supportsForeignKeyConstraints()
  1863. {
  1864. return true;
  1865. }
  1866. /**
  1867. * Does this platform supports onUpdate in foreign key constraints?
  1868. *
  1869. * @return bool
  1870. */
  1871. public function supportsForeignKeyOnUpdate()
  1872. {
  1873. return ($this->supportsForeignKeyConstraints() && true);
  1874. }
  1875. /**
  1876. * Whether the platform supports database schemas.
  1877. *
  1878. * @return boolean
  1879. */
  1880. public function supportsSchemas()
  1881. {
  1882. return false;
  1883. }
  1884. /**
  1885. * Some databases don't allow to create and drop databases at all or only with certain tools.
  1886. *
  1887. * @return bool
  1888. */
  1889. public function supportsCreateDropDatabase()
  1890. {
  1891. return true;
  1892. }
  1893. /**
  1894. * Whether the platform supports getting the affected rows of a recent
  1895. * update/delete type query.
  1896. *
  1897. * @return boolean
  1898. */
  1899. public function supportsGettingAffectedRows()
  1900. {
  1901. return true;
  1902. }
  1903. /**
  1904. * Does this plaform support to add inline column comments as postfix.
  1905. *
  1906. * @return bool
  1907. */
  1908. public function supportsInlineColumnComments()
  1909. {
  1910. return false;
  1911. }
  1912. /**
  1913. * Does this platform support the propriortary synatx "COMMENT ON asset"
  1914. *
  1915. * @return bool
  1916. */
  1917. public function supportsCommentOnStatement()
  1918. {
  1919. return false;
  1920. }
  1921. public function getIdentityColumnNullInsertSQL()
  1922. {
  1923. return "";
  1924. }
  1925. /**
  1926. * Gets the format string, as accepted by the date() function, that describes
  1927. * the format of a stored datetime value of this platform.
  1928. *
  1929. * @return string The format string.
  1930. */
  1931. public function getDateTimeFormatString()
  1932. {
  1933. return 'Y-m-d H:i:s';
  1934. }
  1935. /**
  1936. * Gets the format string, as accepted by the date() function, that describes
  1937. * the format of a stored datetime with timezone value of this platform.
  1938. *
  1939. * @return string The format string.
  1940. */
  1941. public function getDateTimeTzFormatString()
  1942. {
  1943. return 'Y-m-d H:i:s';
  1944. }
  1945. /**
  1946. * Gets the format string, as accepted by the date() function, that describes
  1947. * the format of a stored date value of this platform.
  1948. *
  1949. * @return string The format string.
  1950. */
  1951. public function getDateFormatString()
  1952. {
  1953. return 'Y-m-d';
  1954. }
  1955. /**
  1956. * Gets the format string, as accepted by the date() function, that describes
  1957. * the format of a stored time value of this platform.
  1958. *
  1959. * @return string The format string.
  1960. */
  1961. public function getTimeFormatString()
  1962. {
  1963. return 'H:i:s';
  1964. }
  1965. /**
  1966. * Modify limit query
  1967. *
  1968. * @param string $query
  1969. * @param int $limit
  1970. * @param int $offset
  1971. * @return string
  1972. */
  1973. final public function modifyLimitQuery($query, $limit, $offset = null)
  1974. {
  1975. if ( $limit !== null) {
  1976. $limit = (int)$limit;
  1977. }
  1978. if ( $offset !== null) {
  1979. $offset = (int)$offset;
  1980. }
  1981. return $this->doModifyLimitQuery($query, $limit, $offset);
  1982. }
  1983. /**
  1984. * @param string $query
  1985. * @param int $limit
  1986. * @param int $offset
  1987. * @return string
  1988. */
  1989. protected function doModifyLimitQuery($query, $limit, $offset)
  1990. {
  1991. if ( $limit !== null) {
  1992. $query .= ' LIMIT ' . $limit;
  1993. }
  1994. if ( $offset !== null) {
  1995. $query .= ' OFFSET ' . $offset;
  1996. }
  1997. return $query;
  1998. }
  1999. /**
  2000. * Gets the character casing of a column in an SQL result set of this platform.
  2001. *
  2002. * @param string $column The column name for which to get the correct character casing.
  2003. * @return string The column name in the character casing used in SQL result sets.
  2004. */
  2005. public function getSQLResultCasing($column)
  2006. {
  2007. return $column;
  2008. }
  2009. /**
  2010. * Makes any fixes to a name of a schema element (table, sequence, ...) that are required
  2011. * by restrictions of the platform, like a maximum length.
  2012. *
  2013. * @param string $schemaName
  2014. * @return string
  2015. */
  2016. public function fixSchemaElementName($schemaElementName)
  2017. {
  2018. return $schemaElementName;
  2019. }
  2020. /**
  2021. * Maximum length of any given databse identifier, like tables or column names.
  2022. *
  2023. * @return int
  2024. */
  2025. public function getMaxIdentifierLength()
  2026. {
  2027. return 63;
  2028. }
  2029. /**
  2030. * Get the insert sql for an empty insert statement
  2031. *
  2032. * @param string $tableName
  2033. * @param string $identifierColumnName
  2034. * @return string $sql
  2035. */
  2036. public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
  2037. {
  2038. return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)';
  2039. }
  2040. /**
  2041. * Generate a Truncate Table SQL statement for a given table.
  2042. *
  2043. * Cascade is not supported on many platforms but would optionally cascade the truncate by
  2044. * following the foreign keys.
  2045. *
  2046. * @param string $tableName
  2047. * @param bool $cascade
  2048. * @return string
  2049. */
  2050. public function getTruncateTableSQL($tableName, $cascade = false)
  2051. {
  2052. return 'TRUNCATE '.$tableName;
  2053. }
  2054. /**
  2055. * This is for test reasons, many vendors have special requirements for dummy statements.
  2056. *
  2057. * @return string
  2058. */
  2059. public function getDummySelectSQL()
  2060. {
  2061. return 'SELECT 1';
  2062. }
  2063. /**
  2064. * Generate SQL to create a new savepoint
  2065. *
  2066. * @param string $savepoint
  2067. * @return string
  2068. */
  2069. public function createSavePoint($savepoint)
  2070. {
  2071. return 'SAVEPOINT ' . $savepoint;
  2072. }
  2073. /**
  2074. * Generate SQL to release a savepoint
  2075. *
  2076. * @param string $savepoint
  2077. * @return string
  2078. */
  2079. public function releaseSavePoint($savepoint)
  2080. {
  2081. return 'RELEASE SAVEPOINT ' . $savepoint;
  2082. }
  2083. /**
  2084. * Generate SQL to rollback a savepoint
  2085. *
  2086. * @param string $savepoint
  2087. * @return string
  2088. */
  2089. public function rollbackSavePoint($savepoint)
  2090. {
  2091. return 'ROLLBACK TO SAVEPOINT ' . $savepoint;
  2092. }
  2093. /**
  2094. * Return the keyword list instance of this platform.
  2095. *
  2096. * Throws exception if no keyword list is specified.
  2097. *
  2098. * @throws DBALException
  2099. * @return KeywordList
  2100. */
  2101. final public function getReservedKeywordsList()
  2102. {
  2103. $class = $this->getReservedKeywordsClass();
  2104. $keywords = new $class;
  2105. if (!$keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList) {
  2106. throw DBALException::notSupported(__METHOD__);
  2107. }
  2108. return $keywords;
  2109. }
  2110. /**
  2111. * The class name of the reserved keywords list.
  2112. *
  2113. * @return string
  2114. */
  2115. protected function getReservedKeywordsClass()
  2116. {
  2117. throw DBALException::notSupported(__METHOD__);
  2118. }
  2119. }