From c755b0cb143e1616bed0c56d0f6423ed2c03aa79 Mon Sep 17 00:00:00 2001 From: Gunter Grodotzki Date: Tue, 16 Jan 2018 12:36:43 +0200 Subject: [PATCH] make faster mebbe... (#2) --- app/Transformer/Transform.php | 37 ++++++++------- composer.json | 8 ++-- composer.lock | 62 +------------------------- src/Parser/Insert.php | 84 +++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 80 deletions(-) create mode 100644 src/Parser/Insert.php diff --git a/app/Transformer/Transform.php b/app/Transformer/Transform.php index fae9281..3d150e5 100644 --- a/app/Transformer/Transform.php +++ b/app/Transformer/Transform.php @@ -3,13 +3,14 @@ namespace App\Transformer; use Exception; -use PhpMyAdmin\SqlParser\Parser; -use PhpMyAdmin\SqlParser\Statements\InsertStatement; +use MyFormer\Parser\Insert as InsertParser; class Transform { protected $mappings = []; + protected $transformers = []; + public function __construct(array $mappings) { $this->mappings = $mappings; @@ -28,31 +29,35 @@ public function transform($row) } try { - $parser = new Parser($row); + $insert = new InsertParser($row); } catch(Exception $e) { return $row; } - $insert = $parser->statements[0]; $mappings = $this->mappings[$table]; - $new_values = $this->map($insert, $mappings); - - $insert->values[0] = new \PhpMyAdmin\SqlParser\Components\ArrayObj(array_values($new_values)); + $new_values = $this->map(array_combine($insert->columns, $insert->values), $mappings); - return $insert->build(); + return sprintf( + 'INSERT INTO `%s` (`%s`) VALUES (%s);', + $table, + implode('`, `', array_keys($new_values)), + implode(', ', array_values($new_values)) + ); } - protected function map(InsertStatement $insert, array $mappings) + protected function map(array $values, array $mappings) { - $values = array_combine($insert->into->columns, $insert->values[0]->raw); - foreach ($mappings as $column => $rule) { - $class_name = 'App\\Transformer\\Transformers\\' . key($rule); - $transformer = new $class_name; - $transformer->setParam(current($rule)); - $values[$column] = $transformer->transform($values, $column); - unset($transformer); + $rule_name = key($rule); + + if (!isset($this->transformers[$rule_name])) { + $class_name = 'App\\Transformer\\Transformers\\' . $rule_name; + $this->transformers[$rule_name] = new $class_name; + $this->transformers[$rule_name]->setParam(current($rule)); + } + + $values[$column] = $this->transformers[$rule_name]->transform($values, $column); } return $values; diff --git a/composer.json b/composer.json index da2f418..42ea97a 100644 --- a/composer.json +++ b/composer.json @@ -11,10 +11,12 @@ ], "require": { "php": ">=7.1.0", - "symfony/console": "^4.0", - "phpmyadmin/sql-parser": "^4.2" + "symfony/console": "^4.0" }, "autoload": { - "psr-4": {"App\\": "app/"} + "psr-4": { + "App\\": "app/", + "MyFormer\\": "src/" + } } } diff --git a/composer.lock b/composer.lock index 90c8ba6..bbc0a3e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,68 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "e7122b0518cde16fa8ca8637153bc948", + "content-hash": "3bdd5b15cbf2187a95196427dbdd8b50", "packages": [ - { - "name": "phpmyadmin/sql-parser", - "version": "v4.2.4", - "source": { - "type": "git", - "url": "https://github.com/phpmyadmin/sql-parser.git", - "reference": "10f4e571ba3903593ea7e2c4ec5304f3c0323a98" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/10f4e571ba3903593ea7e2c4ec5304f3c0323a98", - "reference": "10f4e571ba3903593ea7e2c4ec5304f3c0323a98", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "symfony/polyfill-mbstring": "^1.3" - }, - "conflict": { - "phpmyadmin/motranslator": "<3.0" - }, - "require-dev": { - "phpunit/php-code-coverage": "*", - "phpunit/phpunit": "~4.8 || ~5.7" - }, - "suggest": { - "ext-mbstring": "For best performance", - "phpmyadmin/motranslator": "Translate messages to your favorite locale" - }, - "bin": [ - "bin/highlight-query", - "bin/lint-query" - ], - "type": "library", - "autoload": { - "psr-4": { - "PhpMyAdmin\\SqlParser\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0+" - ], - "authors": [ - { - "name": "The phpMyAdmin Team", - "email": "developers@phpmyadmin.net", - "homepage": "https://www.phpmyadmin.net/team/" - } - ], - "description": "A validating SQL lexer and parser with a focus on MySQL dialect.", - "homepage": "https://github.com/phpmyadmin/sql-parser", - "keywords": [ - "analysis", - "lexer", - "parser", - "sql" - ], - "time": "2017-12-06T09:53:26+00:00" - }, { "name": "symfony/console", "version": "v4.0.3", diff --git a/src/Parser/Insert.php b/src/Parser/Insert.php new file mode 100644 index 0000000..842b699 --- /dev/null +++ b/src/Parser/Insert.php @@ -0,0 +1,84 @@ +parse($raw); + } + + public function parse($raw) + { + if (preg_match('~^INSERT INTO `([^`]+)` \((.*)\) VALUES \((.*)\);$~i', $raw, $matches)) { + $this->table = $matches[1]; + $this->splitColumns($matches[2]); + $this->splitValues($matches[3]); + } + } + + protected function splitColumns($raw) + { + // https://stackoverflow.com/a/6243797/567193 + $raw_columns = preg_split('~\\\\.(*SKIP)(*FAIL)|,\s*~s', $raw); + foreach ($raw_columns as $raw_column) { + $this->columns[] = trim($raw_column, '`'); + } + } + + protected function splitValues($raw) + { + $str_len = strlen($raw); + $cur = 0; + $tok_end = ''; + + for ($i = 0; $i < $str_len; ++$i) { + + // token-end reached + if ($raw[$i] === $tok_end) { + // skip next char if token-end is not the delimiter + if ($tok_end === "'") { + $this->values[$cur] .= $raw[$i]; + ++$i; + } + ++$cur; + $tok_end = ''; + continue; + } + + // token-end not yet defined + if ($tok_end === '') { + // skip whitespaces + if ($raw[$i] === ' ') { + continue; + } + + // define token-end + if ($raw[$i] === "'") { + $tok_end = "'"; + } else { + $tok_end = ','; + } + } + + // don't tokenise escaped + if ($raw[$i] === '\\') { + $this->values[$cur] .= $raw[$i] . $raw[++$i]; + continue; + } + + if (!isset($this->values[$cur])) { + $this->values[$cur] = ''; + } + + $this->values[$cur] .= $raw[$i]; + } + } +}