COciCommandBuilder.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. /**
  3. * COciCommandBuilder class file.
  4. *
  5. * @author Ricardo Grana <rickgrana@yahoo.com.br>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * COciCommandBuilder provides basic methods to create query commands for tables.
  12. *
  13. * @author Ricardo Grana <rickgrana@yahoo.com.br>
  14. * @package system.db.schema.oci
  15. */
  16. class COciCommandBuilder extends CDbCommandBuilder
  17. {
  18. /**
  19. * @var integer the last insertion ID
  20. */
  21. public $returnID;
  22. /**
  23. * Returns the last insertion ID for the specified table.
  24. * @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
  25. * @return mixed last insertion id. Null is returned if no sequence name.
  26. */
  27. public function getLastInsertID($table)
  28. {
  29. return $this->returnID;
  30. }
  31. /**
  32. * Alters the SQL to apply LIMIT and OFFSET.
  33. * Default implementation is applicable for PostgreSQL, MySQL and SQLite.
  34. * @param string $sql SQL query string without LIMIT and OFFSET.
  35. * @param integer $limit maximum number of rows, -1 to ignore limit.
  36. * @param integer $offset row offset, -1 to ignore offset.
  37. * @return string SQL with LIMIT and OFFSET
  38. */
  39. public function applyLimit($sql,$limit,$offset)
  40. {
  41. if (($limit < 0) and ($offset < 0)) return $sql;
  42. $filters = array();
  43. if($offset>0){
  44. $filters[] = 'rowNumId > '.(int)$offset;
  45. }
  46. if($limit>=0){
  47. $filters[]= 'rownum <= '.(int)$limit;
  48. }
  49. if (count($filters) > 0){
  50. $filter = implode(' and ', $filters);
  51. $filter= " WHERE ".$filter;
  52. }else{
  53. $filter = '';
  54. }
  55. $sql = <<<EOD
  56. WITH USER_SQL AS ({$sql}),
  57. PAGINATION AS (SELECT USER_SQL.*, rownum as rowNumId FROM USER_SQL)
  58. SELECT *
  59. FROM PAGINATION
  60. {$filter}
  61. EOD;
  62. return $sql;
  63. }
  64. /**
  65. * Creates an INSERT command.
  66. * @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
  67. * @param array $data data to be inserted (column name=>column value). If a key is not a valid column name, the corresponding value will be ignored.
  68. * @return CDbCommand insert command
  69. */
  70. public function createInsertCommand($table,$data)
  71. {
  72. $this->ensureTable($table);
  73. $fields=array();
  74. $values=array();
  75. $placeholders=array();
  76. $i=0;
  77. foreach($data as $name=>$value)
  78. {
  79. if(($column=$table->getColumn($name))!==null && ($value!==null || $column->allowNull))
  80. {
  81. $fields[]=$column->rawName;
  82. if($value instanceof CDbExpression)
  83. {
  84. $placeholders[]=$value->expression;
  85. foreach($value->params as $n=>$v)
  86. $values[$n]=$v;
  87. }
  88. else
  89. {
  90. $placeholders[]=self::PARAM_PREFIX.$i;
  91. $values[self::PARAM_PREFIX.$i]=$column->typecast($value);
  92. $i++;
  93. }
  94. }
  95. }
  96. $sql="INSERT INTO {$table->rawName} (".implode(', ',$fields).') VALUES ('.implode(', ',$placeholders).')';
  97. if(is_string($table->primaryKey) && ($column=$table->getColumn($table->primaryKey))!==null && $column->type!=='string')
  98. {
  99. $sql.=' RETURNING '.$column->rawName.' INTO :RETURN_ID';
  100. $command=$this->getDbConnection()->createCommand($sql);
  101. $command->bindParam(':RETURN_ID', $this->returnID, PDO::PARAM_INT, 12);
  102. $table->sequenceName='RETURN_ID';
  103. }
  104. else
  105. $command=$this->getDbConnection()->createCommand($sql);
  106. foreach($values as $name=>$value)
  107. $command->bindValue($name,$value);
  108. return $command;
  109. }
  110. /**
  111. * Creates a multiple INSERT command.
  112. * This method could be used to achieve better performance during insertion of the large
  113. * amount of data into the database tables.
  114. * @param mixed $table the table schema ({@link CDbTableSchema}) or the table name (string).
  115. * @param array[] $data list data to be inserted, each value should be an array in format (column name=>column value).
  116. * If a key is not a valid column name, the corresponding value will be ignored.
  117. * @return CDbCommand multiple insert command
  118. * @since 1.1.14
  119. */
  120. public function createMultipleInsertCommand($table,array $data)
  121. {
  122. $templates=array(
  123. 'main'=>'INSERT ALL {{rowInsertValues}} SELECT * FROM dual',
  124. 'columnInsertValue'=>'{{value}}',
  125. 'columnInsertValueGlue'=>', ',
  126. 'rowInsertValue'=>'INTO {{tableName}} ({{columnInsertNames}}) VALUES ({{columnInsertValues}})',
  127. 'rowInsertValueGlue'=>' ',
  128. 'columnInsertNameGlue'=>', ',
  129. );
  130. return $this->composeMultipleInsertCommand($table,$data,$templates);
  131. }
  132. }