1<?php
2/**
3 * ReferenceDefinitionProcessor.php
4 *
5 * This file implements the processor reference definition part of the CREATE TABLE statements.
6 *
7 * Copyright (c) 2010-2012, Justin Swanhart
8 * with contributions by André Rothe <arothe@phosco.info, phosco@gmx.de>
9 *
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without modification,
13 * are permitted provided that the following conditions are met:
14 *
15 *   * Redistributions of source code must retain the above copyright notice,
16 *     this list of conditions and the following disclaimer.
17 *   * Redistributions in binary form must reproduce the above copyright notice,
18 *     this list of conditions and the following disclaimer in the documentation
19 *     and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 * DAMAGE.
31 */
32
33namespace PHPSQLParser\processors;
34use PHPSQLParser\utils\ExpressionType;
35
36/**
37 *
38 * This class processes the reference definition part of the CREATE TABLE statements.
39 *
40 * @author arothe
41 */
42class ReferenceDefinitionProcessor extends AbstractProcessor {
43
44    protected function buildReferenceDef($expr, $base_expr, $key) {
45        $expr['till'] = $key;
46        $expr['base_expr'] = $base_expr;
47        return $expr;
48    }
49
50    public function process($tokens) {
51
52        $expr = array('expr_type' => ExpressionType::REFERENCE, 'base_expr' => false, 'sub_tree' => array());
53        $base_expr = '';
54
55        foreach ($tokens as $key => $token) {
56
57            $trim = trim($token);
58            $base_expr .= $token;
59
60            if ($trim === '') {
61                continue;
62            }
63
64            $upper = strtoupper($trim);
65
66            switch ($upper) {
67
68            case ',':
69            # we stop on a single comma
70            # or at the end of the array $tokens
71                $expr = $this->buildReferenceDef($expr, trim(substr($base_expr, 0, -strlen($token))), $key - 1);
72                break 2;
73
74            case 'REFERENCES':
75                $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
76                $currCategory = $upper;
77                break;
78
79            case 'MATCH':
80                if ($currCategory === 'REF_COL_LIST') {
81                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
82                    $currCategory = 'REF_MATCH';
83                    continue 2;
84                }
85                # else?
86                break;
87
88            case 'FULL':
89            case 'PARTIAL':
90            case 'SIMPLE':
91                if ($currCategory === 'REF_MATCH') {
92                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
93                    $expr['match'] = $upper;
94                    $currCategory = 'REF_COL_LIST';
95                    continue 2;
96                }
97                # else?
98                break;
99
100            case 'ON':
101                if ($currCategory === 'REF_COL_LIST') {
102                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
103                    $currCategory = 'REF_ACTION';
104                    continue 2;
105                }
106                # else ?
107                break;
108
109            case 'UPDATE':
110            case 'DELETE':
111                if ($currCategory === 'REF_ACTION') {
112                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
113                    $currCategory = 'REF_OPTION_' . $upper;
114                    continue 2;
115                }
116                # else ?
117                break;
118
119            case 'RESTRICT':
120            case 'CASCADE':
121                if (strpos($currCategory, 'REF_OPTION_') === 0) {
122                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
123                    $expr['on_' . strtolower(substr($currCategory, -6))] = $upper;
124                    continue 2;
125                }
126                # else ?
127                break;
128
129            case 'SET':
130            case 'NO':
131                if (strpos($currCategory, 'REF_OPTION_') === 0) {
132                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
133                    $expr['on_' . strtolower(substr($currCategory, -6))] = $upper;
134                    $currCategory = 'SEC_' . $currCategory;
135                    continue 2;
136                }
137                # else ?
138                break;
139
140            case 'NULL':
141            case 'ACTION':
142                if (strpos($currCategory, 'SEC_REF_OPTION_') === 0) {
143                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim);
144                    $expr['on_' . strtolower(substr($currCategory, -6))] .= ' ' . $upper;
145                    $currCategory = 'REF_COL_LIST';
146                    continue 2;
147                }
148                # else ?
149                break;
150
151            default:
152                switch ($currCategory) {
153
154                case 'REFERENCES':
155                    if ($upper[0] === '(' && substr($upper, -1) === ')') {
156                        # index_col_name list
157                        $processor = new IndexColumnListProcessor($this->options);
158                        $cols = $processor->process($this->removeParenthesisFromStart($trim));
159                        $expr['sub_tree'][] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim,
160                                                    'sub_tree' => $cols);
161                        $currCategory = 'REF_COL_LIST';
162                        continue 3;
163                    }
164                    # foreign key reference table name
165                    $expr['sub_tree'][] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim,
166                                                'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim));
167                    continue 3;
168
169                default:
170                # else ?
171                    break;
172                }
173                break;
174            }
175        }
176
177        if (!isset($expr['till'])) {
178            $expr = $this->buildReferenceDef($expr, trim($base_expr), -1);
179        }
180        return $expr;
181    }
182}
183?>