Skip to content

Commit 3679815

Browse files
committed
Implemented support for transactions.
1 parent e1b91ed commit 3679815

9 files changed

Lines changed: 133 additions & 55 deletions

File tree

src/Component.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public static function parse(
3939
) {
4040
// This method should be abstract, but it can't be both static and
4141
// abstract.
42-
return null;
42+
throw new \Exception('Not implemented yet.');
4343
}
4444

4545
/**
@@ -56,7 +56,7 @@ public static function build($component)
5656
{
5757
// This method should be abstract, but it can't be both static and
5858
// abstract.
59-
return null;
59+
throw new \Exception('Not implemented yet.');
6060
}
6161

6262
/**

src/Components/SetOperation.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,22 @@ public static function parse(Parser $parser, TokensList $list, array $options =
117117
--$list->idx;
118118
return $ret;
119119
}
120+
121+
/**
122+
* @param SetOperation|SetOperation[] $component The component to be built.
123+
*
124+
* @return string
125+
*/
126+
public static function build($component)
127+
{
128+
if (is_array($component)) {
129+
$ret = array();
130+
foreach ($component as $c) {
131+
$ret[] = static::build($c);
132+
}
133+
return implode(", ", $ret);
134+
} else {
135+
return $component->column . ' = ' . $component->value;
136+
}
137+
}
120138
}

src/Contexts/ContextMySql50000.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,18 @@ class ContextMySql50000 extends Context
144144
'SQL_CALC_FOUND_ROWS' => 3,
145145

146146
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
147-
'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'NO ACTION' => 7,
148-
'ON DELETE' => 7, 'ON UPDATE' => 7,
149-
'INNER JOIN' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
150-
'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
147+
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
148+
'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
149+
'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
150+
'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
151151
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
152152
'DATA DIRECTORY' => 7,
153153
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
154154
'GENERATED ALWAYS' => 7,
155+
'START TRANSACTION' => 7,
156+
'SELECT TRANSACTION' => 7,
155157
'DEFAULT CHARACTER SET' => 7,
158+
'WITH CONSISTENT SNAPSHOT' => 7,
156159

157160
'XML' => 9,
158161
'ENUM' => 9, 'TEXT' => 9,

src/Contexts/ContextMySql50100.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,18 @@ class ContextMySql50100 extends Context
156156
'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
157157

158158
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
159-
'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'NO ACTION' => 7,
160-
'ON DELETE' => 7, 'ON UPDATE' => 7,
161-
'INNER JOIN' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
162-
'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
159+
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
160+
'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
161+
'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
162+
'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
163163
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
164164
'DATA DIRECTORY' => 7,
165165
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
166166
'GENERATED ALWAYS' => 7,
167+
'START TRANSACTION' => 7,
168+
'SELECT TRANSACTION' => 7,
167169
'DEFAULT CHARACTER SET' => 7,
170+
'WITH CONSISTENT SNAPSHOT' => 7,
168171

169172
'XML' => 9,
170173
'ENUM' => 9, 'TEXT' => 9,

src/Contexts/ContextMySql50500.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,18 @@ class ContextMySql50500 extends Context
161161
'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
162162

163163
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
164-
'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'NO ACTION' => 7,
165-
'ON DELETE' => 7, 'ON UPDATE' => 7,
166-
'INNER JOIN' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
167-
'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
164+
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
165+
'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
166+
'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
167+
'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
168168
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
169169
'DATA DIRECTORY' => 7,
170170
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
171171
'GENERATED ALWAYS' => 7,
172+
'START TRANSACTION' => 7,
173+
'SELECT TRANSACTION' => 7,
172174
'DEFAULT CHARACTER SET' => 7,
175+
'WITH CONSISTENT SNAPSHOT' => 7,
173176

174177
'XML' => 9,
175178
'ENUM' => 9, 'TEXT' => 9,

src/Contexts/ContextMySql50600.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,18 @@ class ContextMySql50600 extends Context
166166
'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
167167

168168
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
169-
'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'NO ACTION' => 7,
170-
'ON DELETE' => 7, 'ON UPDATE' => 7,
171-
'INNER JOIN' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
172-
'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
169+
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
170+
'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
171+
'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
172+
'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
173173
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
174174
'DATA DIRECTORY' => 7,
175175
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
176176
'GENERATED ALWAYS' => 7,
177+
'START TRANSACTION' => 7,
178+
'SELECT TRANSACTION' => 7,
177179
'DEFAULT CHARACTER SET' => 7,
180+
'WITH CONSISTENT SNAPSHOT' => 7,
178181

179182
'XML' => 9,
180183
'ENUM' => 9, 'TEXT' => 9,

src/Contexts/ContextMySql50700.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,18 @@ class ContextMySql50700 extends Context
174174
'MASTER_SSL_VERIFY_SERVER_CERT' => 3,
175175

176176
'GROUP BY' => 7, 'NOT NULL' => 7, 'ORDER BY' => 7, 'SET NULL' => 7,
177-
'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7, 'NO ACTION' => 7,
178-
'ON DELETE' => 7, 'ON UPDATE' => 7,
179-
'INNER JOIN' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
180-
'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
177+
'AND CHAIN' => 7, 'FULL JOIN' => 7, 'IF EXISTS' => 7, 'LEFT JOIN' => 7,
178+
'NO ACTION' => 7, 'ON DELETE' => 7, 'ON UPDATE' => 7,
179+
'INNER JOIN' => 7, 'NO RELEASE' => 7, 'OR REPLACE' => 7, 'RIGHT JOIN' => 7,
180+
'AND NO CHAIN' => 7, 'FOR EACH ROW' => 7, 'SQL SECURITY' => 7,
181181
'CHARACTER SET' => 7, 'IF NOT EXISTS' => 7,
182182
'DATA DIRECTORY' => 7,
183183
'DEFAULT CHARSET' => 7, 'DEFAULT COLLATE' => 7, 'INDEX DIRECTORY' => 7,
184184
'GENERATED ALWAYS' => 7,
185+
'START TRANSACTION' => 7,
186+
'SELECT TRANSACTION' => 7,
185187
'DEFAULT CHARACTER SET' => 7,
188+
'WITH CONSISTENT SNAPSHOT' => 7,
186189

187190
'XML' => 9,
188191
'ENUM' => 9, 'TEXT' => 9,

src/Parser.php

Lines changed: 63 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ function __($str)
2828

2929
namespace SqlParser {
3030

31-
use SqlParser\Statements\SelectStatement;
3231
use SqlParser\Exceptions\ParserException;
32+
use SqlParser\Statements\SelectStatement;
33+
use SqlParser\Statements\TransactionStatement;
3334

3435
/**
3536
* Takes multiple tokens (contained in a Lexer instance) as input and builds a
@@ -50,47 +51,54 @@ class Parser
5051
*/
5152
public static $STATEMENT_PARSERS = array(
5253

53-
'EXPLAIN' => 'SqlParser\\Statements\\ExplainStatement',
54+
'EXPLAIN' => 'SqlParser\\Statements\\ExplainStatement',
5455

5556
// Table Maintenance Statements
5657
// https://dev.mysql.com/doc/refman/5.7/en/table-maintenance-sql.html
57-
'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement',
58-
'BACKUP' => 'SqlParser\\Statements\\BackupStatement',
59-
'CHECK' => 'SqlParser\\Statements\\CheckStatement',
60-
'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement',
61-
'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement',
62-
'REPAIR' => 'SqlParser\\Statements\\RepairStatement',
63-
'RESTORE' => 'SqlParser\\Statements\\RestoreStatement',
58+
'ANALYZE' => 'SqlParser\\Statements\\AnalyzeStatement',
59+
'BACKUP' => 'SqlParser\\Statements\\BackupStatement',
60+
'CHECK' => 'SqlParser\\Statements\\CheckStatement',
61+
'CHECKSUM' => 'SqlParser\\Statements\\ChecksumStatement',
62+
'OPTIMIZE' => 'SqlParser\\Statements\\OptimizeStatement',
63+
'REPAIR' => 'SqlParser\\Statements\\RepairStatement',
64+
'RESTORE' => 'SqlParser\\Statements\\RestoreStatement',
6465

6566
// Database Administration Statements
6667
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-server-administration.html
67-
'SET' => '',
68-
'SHOW' => 'SqlParser\\Statements\\ShowStatement',
68+
'SET' => '',
69+
'SHOW' => 'SqlParser\\Statements\\ShowStatement',
6970

7071
// Data Definition Statements.
7172
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-definition.html
72-
'ALTER' => 'SqlParser\\Statements\\AlterStatement',
73-
'CREATE' => 'SqlParser\\Statements\\CreateStatement',
74-
'DROP' => 'SqlParser\\Statements\\DropStatement',
75-
'RENAME' => 'SqlParser\\Statements\\RenameStatement',
76-
'TRUNCATE' => 'SqlParser\\Statements\\TruncateStatement',
73+
'ALTER' => 'SqlParser\\Statements\\AlterStatement',
74+
'CREATE' => 'SqlParser\\Statements\\CreateStatement',
75+
'DROP' => 'SqlParser\\Statements\\DropStatement',
76+
'RENAME' => 'SqlParser\\Statements\\RenameStatement',
77+
'TRUNCATE' => 'SqlParser\\Statements\\TruncateStatement',
7778

7879
// Data Manipulation Statements.
7980
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-data-manipulation.html
80-
'CALL' => 'SqlParser\\Statements\\CallStatement',
81-
'DELETE' => 'SqlParser\\Statements\\DeleteStatement',
82-
'DO' => '',
83-
'HANDLER' => '',
84-
'INSERT' => 'SqlParser\\Statements\\InsertStatement',
85-
'LOAD' => '',
86-
'REPLACE' => 'SqlParser\\Statements\\ReplaceStatement',
87-
'SELECT' => 'SqlParser\\Statements\\SelectStatement',
88-
'UPDATE' => 'SqlParser\\Statements\\UpdateStatement',
81+
'CALL' => 'SqlParser\\Statements\\CallStatement',
82+
'DELETE' => 'SqlParser\\Statements\\DeleteStatement',
83+
'DO' => '',
84+
'HANDLER' => '',
85+
'INSERT' => 'SqlParser\\Statements\\InsertStatement',
86+
'LOAD' => '',
87+
'REPLACE' => 'SqlParser\\Statements\\ReplaceStatement',
88+
'SELECT' => 'SqlParser\\Statements\\SelectStatement',
89+
'UPDATE' => 'SqlParser\\Statements\\UpdateStatement',
8990

9091
// Prepared Statements.
9192
// https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
92-
'PREPARE' => '',
93-
'EXECUTE' => '',
93+
'PREPARE' => '',
94+
'EXECUTE' => '',
95+
96+
// Transactional and Locking Statements
97+
// https://dev.mysql.com/doc/refman/5.7/en/commit.html
98+
'START TRANSACTION' => 'SqlParser\\Statements\\TransactionStatement',
99+
'BEGIN' => 'SqlParser\\Statements\\TransactionStatement',
100+
'COMMIT' => 'SqlParser\\Statements\\TransactionStatement',
101+
'ROLLBACK' => 'SqlParser\\Statements\\TransactionStatement',
94102
);
95103

96104
/**
@@ -311,6 +319,13 @@ public function __construct($list = null, $strict = false)
311319
public function parse()
312320
{
313321

322+
/**
323+
* Last transaction.
324+
*
325+
* @var TransactionStatement
326+
*/
327+
$lastTransaction = null;
328+
314329
/**
315330
* Last parsed statement.
316331
* @var Statement $lastStatement
@@ -400,21 +415,40 @@ public function parse()
400415
$statement->last = $list->idx;
401416
$prevLastIdx = $list->idx;
402417

403-
// Finally, storing the statement.
418+
// Handles unions.
404419
if (($inUnion)
405420
&& ($lastStatement instanceof SelectStatement)
406421
&& ($statement instanceof SelectStatement)
407422
) {
423+
408424
/**
409425
* Last SELECT statement.
410426
* @var SelectStatement $lastStatement
411427
*/
412428
$lastStatement->union[] = $statement;
413429
$inUnion = false;
430+
continue;
431+
}
432+
433+
// Handles transactions.
434+
if ($statement instanceof TransactionStatement) {
435+
if ($statement->type === TransactionStatement::TYPE_BEGIN) {
436+
$lastTransaction = $statement;
437+
$this->statements[] = $statement;
438+
} elseif ($statement->type === TransactionStatement::TYPE_END) {
439+
$lastTransaction->end = $statement;
440+
$lastTransaction = null;
441+
}
442+
continue;
443+
}
444+
445+
// Finally, storing the statement.
446+
if ($lastTransaction !== null) {
447+
$lastTransaction->statements[] = $statement;
414448
} else {
415449
$this->statements[] = $statement;
416-
$lastStatement = $statement;
417450
}
451+
$lastStatement = $statement;
418452

419453
}
420454
}

tests/Components/FragmentTest.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,27 @@
55
use SqlParser\Component;
66
use SqlParser\Parser;
77
use SqlParser\TokensList;
8-
use SqlParser\Components\ArrayObj;
98

109
use SqlParser\Tests\TestCase;
1110

1211
class ComponentTest extends TestCase
1312
{
1413

15-
public function testDummy()
14+
/**
15+
* @expectedException \Exception
16+
* @expectedExceptionMessage Not implemented yet.
17+
*/
18+
public function testParse()
1619
{
17-
$this->assertEquals(null, Component::parse(new Parser(), new TokensList()));
18-
$this->assertEquals(null, Component::build(new ArrayObj()));
20+
Component::parse(new Parser(), new TokensList());
21+
}
22+
23+
/**
24+
* @expectedException \Exception
25+
* @expectedExceptionMessage Not implemented yet.
26+
*/
27+
public function testBuild()
28+
{
29+
Component::build(null);
1930
}
2031
}

0 commit comments

Comments
 (0)