* * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/IndexColumnListProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the reference definition part of the CREATE TABLE statements. * * @author arothe */ class ReferenceDefinitionProcessor extends AbstractProcessor { protected function buildReferenceDef($expr, $base_expr, $key) { $expr['till'] = $key; $expr['base_expr'] = $base_expr; return $expr; } public function process($tokens) { $expr = array('expr_type' => ExpressionType::REFERENCE, 'base_expr' => false, 'sub_tree' => array()); $base_expr = ''; foreach ($tokens as $key => $token) { $trim = trim($token); $base_expr .= $token; if ($trim === '') { continue; } $upper = strtoupper($trim); switch ($upper) { case ',': # we stop on a single comma # or at the end of the array $tokens $expr = $this->buildReferenceDef($expr, trim(substr($base_expr, 0, -strlen($token))), $key - 1); break 2; case 'REFERENCES': $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = $upper; break; case 'MATCH': if ($currCategory === 'REF_COL_LIST') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = 'REF_MATCH'; continue 2; } # else? break; case 'FULL': case 'PARTIAL': case 'SIMPLE': if ($currCategory === 'REF_MATCH') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['match'] = $upper; $currCategory = 'REF_COL_LIST'; continue 2; } # else? break; case 'ON': if ($currCategory === 'REF_COL_LIST') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = 'REF_ACTION'; continue 2; } # else ? break; case 'UPDATE': case 'DELETE': if ($currCategory === 'REF_ACTION') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = 'REF_OPTION_' . $upper; continue 2; } # else ? break; case 'RESTRICT': case 'CASCADE': if (strpos($currCategory, 'REF_OPTION_') === 0) { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['on_' . strtolower(substr($currCategory, -6))] = $upper; continue 2; } # else ? break; case 'SET': case 'NO': if (strpos($currCategory, 'REF_OPTION_') === 0) { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['on_' . strtolower(substr($currCategory, -6))] = $upper; $currCategory = 'SEC_' . $currCategory; continue 2; } # else ? break; case 'NULL': case 'ACTION': if (strpos($currCategory, 'SEC_REF_OPTION_') === 0) { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['on_' . strtolower(substr($currCategory, -6))] .= ' ' . $upper; $currCategory = 'REF_COL_LIST'; continue 2; } # else ? break; default: switch ($currCategory) { case 'REFERENCES': if ($upper[0] === '(' && substr($upper, -1) === ')') { # index_col_name list $processor = new IndexColumnListProcessor(); $cols = $processor->process($this->removeParenthesisFromStart($trim)); $expr['sub_tree'][] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $currCategory = 'REF_COL_LIST'; continue 3; } # foreign key reference table name $expr['sub_tree'][] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); continue 3; default: # else ? break; } break; } } if (!isset($expr['till'])) { $expr = $this->buildReferenceDef($expr, trim($base_expr), -1); } return $expr; } } ?>