drupal-civicrm/sites/all/modules/civicrm/CRM/Utils/SQL/Insert.php

189 lines
4.1 KiB
PHP
Raw Normal View History

2018-01-14 15:10:16 +02:00
<?php
/**
* Dear God Why Do I Have To Write This (Dumb SQL Builder)
*
* Usage:
* $insert = CRM_Utils_SQL_Insert::into('mytable')
* ->row(array('col1' => '1', 'col2' => '2' ))
* ->row(array('col1' => '2b', 'col2' => '1b'));
* echo $insert->toSQL();
*
* Note: In MySQL, numeric values may be escaped. Except for NULL values,
* it's reasonable for us to simply escape all values by default -- without
* any knowledge of the underlying schema.
*
* Design principles:
* - Portable
* - No knowledge of the underlying SQL API (except for escaping -- CRM_Core_DAO::escapeString)
* - No knowledge of the underlying data model
* - Single file
* - SQL clauses correspond to PHP functions ($select->where("foo_id=123"))
*/
class CRM_Utils_SQL_Insert {
private $verb = 'INSERT INTO';
/**
* @var string
*/
private $table;
/**
* @var array
*/
private $rows;
/**
* Array<string> list of column names
*/
private $columns;
/**
* Create a new INSERT query.
*
* @param string $table
* Table-name and optional alias.
* @return CRM_Utils_SQL_Insert
*/
public static function into($table) {
return new self($table);
}
/**
* Insert a record based on a DAO.
*
* @param \CRM_Core_DAO $dao
* @return \CRM_Utils_SQL_Insert
* @throws \CRM_Core_Exception
*/
public static function dao(CRM_Core_DAO $dao) {
$table = CRM_Core_DAO::getLocaleTableName($dao->getTableName());
$row = array();
foreach ((array) $dao as $key => $value) {
if ($value === 'null') {
$value = NULL; // Blerg!!!
}
// Skip '_foobar' and '{\u00}*_options' and 'N'.
if (preg_match('/[a-zA-Z]/', $key{0}) && $key !== 'N') {
$row[$key] = $value;
}
}
return self::into($table)->row($row);
}
/**
* Create a new SELECT query.
*
* @param string $table
* Table-name and optional alias.
*/
public function __construct($table) {
$this->table = $table;
$this->rows = array();
}
/**
* Get columns.
*
* @param array $columns
*
* @return CRM_Utils_SQL_Insert
* @throws \CRM_Core_Exception
*/
public function columns($columns) {
if ($this->columns !== NULL) {
throw new CRM_Core_Exception("Column order already specified.");
}
$this->columns = $columns;
return $this;
}
/**
* Get rows.
*
* @param array $rows
*
* @return CRM_Utils_SQL_Insert
*/
public function rows($rows) {
foreach ($rows as $row) {
$this->row($row);
}
return $this;
}
/**
* Get row.
*
* @param array $row
*
* @return CRM_Utils_SQL_Insert
* @throws CRM_Core_Exception
*/
public function row($row) {
$columns = array_keys($row);
if ($this->columns === NULL) {
sort($columns);
$this->columns = $columns;
}
elseif (array_diff($this->columns, $columns) !== array()) {
throw new CRM_Core_Exception("Inconsistent column names");
}
$escapedRow = array();
foreach ($this->columns as $column) {
$escapedRow[$column] = $this->escapeString($row[$column]);
}
$this->rows[] = $escapedRow;
return $this;
}
/**
* Use REPLACE INTO instead of INSERT INTO.
*
* @param bool $asReplace
*
* @return CRM_Utils_SQL_Insert
*/
public function usingReplace($asReplace = TRUE) {
$this->verb = $asReplace ? 'REPLACE INTO' : 'INSERT INTO';
return $this;
}
/**
* Escape string.
*
* @param string|NULL $value
*
* @return string
* SQL expression, e.g. "it\'s great" (with-quotes) or NULL (without-quotes)
*/
protected function escapeString($value) {
return $value === NULL ? 'NULL' : '"' . CRM_Core_DAO::escapeString($value) . '"';
}
/**
* Convert to SQL.
*
* @return string
* SQL statement
*/
public function toSQL() {
$columns = "`" . implode('`,`', $this->columns) . "`";
$sql = "{$this->verb} {$this->table} ({$columns}) VALUES";
$nextDelim = '';
foreach ($this->rows as $row) {
$sql .= "{$nextDelim}\n(" . implode(',', $row) . ")";
$nextDelim = ',';
}
$sql .= "\n";
return $sql;
}
}