From e7feaa0b28de06faa148f1649f5486c79a5b2de4 Mon Sep 17 00:00:00 2001 From: Glen Sawyer Date: Wed, 2 Mar 2016 14:18:59 -0700 Subject: [PATCH] Avoid Oracle 30-character identifier limit --- src/Dialect/OracleDialectTrait.php | 29 ++++++++++++++++++++++++++++- src/Statement/OracleStatement.php | 24 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/Dialect/OracleDialectTrait.php b/src/Dialect/OracleDialectTrait.php index 29a743a..115947c 100644 --- a/src/Dialect/OracleDialectTrait.php +++ b/src/Dialect/OracleDialectTrait.php @@ -6,13 +6,17 @@ trait OracleDialectTrait { - use SqlDialectTrait; + use SqlDialectTrait { + quoteIdentifier as origQuoteIdentifier; + } protected $_schemaDialect; protected $_startQuote = '"'; protected $_endQuote = '"'; + public $autoShortenedIdentifiers = []; + /** * {@inheritDoc} * @@ -87,4 +91,27 @@ public function releaseSavePointSQL($name) //Oracle doesn't have "release savepoint" functionality return ''; } + + /** + * VERY HACKY: To avoid Oracle's "No identifiers > 30 characters" + * restriction, at this very low level we'll auto-replace Cake automagic + * aliases like 'SomeLongTableName__some_really_long_field_name' with + * 'XXAUTO_SHORTENED_ID[n]' where [n] is a simple incrementing integer. + * Then in OracleStatement's "fetch" function, we'll undo these + * auto-replacements + * + * {@inheritDoc} + */ + public function quoteIdentifier($identifier) + { + if (preg_match('/^[\w-]+$/', $identifier) && strlen($identifier) > 30) { + $key = array_search($identifier, $this->autoShortenedIdentifiers); + if ($key === false) { + $key = 'XXAUTO_SHORTENED_ID' . (count($this->autoShortenedIdentifiers) + 1); + $this->autoShortenedIdentifiers[$key] = $identifier; + } + $identifier = $key; + } + return $this->origQuoteIdentifier($identifier); + } } diff --git a/src/Statement/OracleStatement.php b/src/Statement/OracleStatement.php index 624a3ac..f943f53 100644 --- a/src/Statement/OracleStatement.php +++ b/src/Statement/OracleStatement.php @@ -73,4 +73,28 @@ public function bind($params, $types) $this->bindValue($index, $value, $type); } } + + /** + * VERY HACKY: Override fetch to UN-auto-shorten identifiers, + * which is done in OracleDialectTrait "quoteIdentifier" + * + * {@inheritDoc} + */ + public function fetch($type = 'num') + { + $row = parent::fetch($type); + if ($type == 'assoc' && is_array($row) && !empty($this->_driver->autoShortenedIdentifiers)) { + //Need to preserve order of row results + $translatedRow = []; + foreach ($row as $key => $val) { + if (array_key_exists($key, $this->_driver->autoShortenedIdentifiers)) { + $translatedRow[$this->_driver->autoShortenedIdentifiers[$key]] = $val; + } else { + $translatedRow[$key] = $val; + } + } + $row = $translatedRow; + } + return $row; + } }