A validating SQL lexer and parser with a focus on MySQL dialect.

Overview

SQL Parser

A validating SQL lexer and parser with a focus on MySQL dialect.

Code status

Tests Code Coverage codecov.io Scrutinizer Code Quality Translation status Packagist Open Source Helpers

Installation

Please use Composer to install:

composer require phpmyadmin/sql-parser

Documentation

The API documentation is available at https://develdocs.phpmyadmin.net/sql-parser/.

Usage

Command line utilities

Command line utility to syntax highlight SQL query:

./vendor/bin/highlight-query --query "SELECT 1"

Command line utility to lint SQL query:

./vendor/bin/lint-query --query "SELECT 1"

Command line utility to tokenize SQL query:

./vendor/bin/tokenize-query --query "SELECT 1"

All commands are able to parse input from stdin (standard in), such as:

echo "SELECT 1" | ./vendor/bin/highlight-query
cat example.sql | ./vendor/bin/lint-query

Formatting SQL query

echo PhpMyAdmin\SqlParser\Utils\Formatter::format($query, ['type' => 'html']);

Discoverying query type

use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Utils\Query;

$query = 'OPTIMIZE TABLE tbl';
$parser = new Parser($query);
$flags = Query::getFlags($parser->statements[0]);

echo $flags['querytype'];

Parsing and building SQL query

require __DIR__ . '/vendor/autoload.php';

$query1 = 'select * from a';
$parser = new PhpMyAdmin\SqlParser\Parser($query1);

// inspect query
var_dump($parser->statements[0]); // outputs object(PhpMyAdmin\SqlParser\Statements\SelectStatement)

// modify query by replacing table a with table b
$table2 = new \PhpMyAdmin\SqlParser\Components\Expression('', 'b', '', '');
$parser->statements[0]->from[0] = $table2;

// build query again from an array of object(PhpMyAdmin\SqlParser\Statements\SelectStatement) to a string
$statement = $parser->statements[0];
$query2 = $statement->build();
var_dump($query2); // outputs string(19) 'SELECT  * FROM `b` '

// Change SQL mode
PhpMyAdmin\SqlParser\Context::setMode('ANSI_QUOTES');

// build the query again using different quotes
$query2 = $statement->build();
var_dump($query2); // outputs string(19) 'SELECT  * FROM "b" '

Localization

You can localize error messages installing phpmyadmin/motranslator version 5.0 or newer:

composer require phpmyadmin/motranslator:^5.0

The locale is automatically detected from your environment, you can also set a different locale

From cli:

LC_ALL=pl ./vendor/bin/lint-query --query "SELECT 1"

From php:

require __DIR__ . '/vendor/autoload.php';

$GLOBALS['lang'] = 'pl';

$query1 = 'select * from a';
$parser = new PhpMyAdmin\SqlParser\Parser($query1);

More information

This library was originally created during the Google Summer of Code 2015 and has been used by phpMyAdmin since version 4.5.

Comments
  • Feature ansi mode, partial solution to #284

    Feature ansi mode, partial solution to #284

    This is very trivial, and I have no idea, what might have been broken by these changes, but phpunit does not complain about anything, so you definitely haven't written enough tests :laughing: /s

    It allows you to retrieve current identifiers quoting char from Context::getIdentifierQuote() based on current SQL Mode set and seems to work well with CLI tools such as lint and highlight-query

    There are still few places, where the backtick is hard-coded, and I'm not sure if I should update these pieces of code with new context-aware solution, but that I probably leave to someone who knows this code-base better.

    I've tested this with sample SQL query from: https://github.com/phpmyadmin/phpmyadmin/issues/15821#issuecomment-578572914

    Fixes: #284

    enhancement 
    opened by smarek 21
  • compatibility with PHP 8.1 (ArrayAccess)

    compatibility with PHP 8.1 (ArrayAccess)

    Do you plan to add compatibility with PHP 8.1?

    Currently I have next messages: PHP Deprecated: Return type of PhpMyAdmin\SqlParser\TokensList::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in phar://sql-parser.phar/src/TokensList.php on line 184

    Deprecated: Return type of PhpMyAdmin\SqlParser\TokensList::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in phar://sql-parser.phar/src/TokensList.php on line 172

    PHP Deprecated: Return type of PhpMyAdmin\SqlParser\TokensList::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in phar://sql-parser.phar/src/TokensList.php on line 156

    PHP Deprecated: Return type of PhpMyAdmin\SqlParser\TokensList::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in phar://sql-parser.phar/src/TokensList.php on line 194

    invalid 
    opened by SailorMax 12
  • Add support for WITH clause (enhancement for syntax highlighter)

    Add support for WITH clause (enhancement for syntax highlighter)

    Currently the SQL syntax highlighter marks the WITH keyword as Unrecognized statement type. MariaDB supports a WITH clause in combination with a SELECT statement since version 10.2.1 (stable=10.2.8), see https://mariadb.com/kb/en/the-mariadb-library/with/

    phpMyAdmin version: 4.7.4

    Sort of relates to phpmyadmin/phpmyadmin#13615 (but not really)

    enhancement 
    opened by stevenwdv 10
  • Add a

    Add a "vendor" top level namespace

    From http://www.php-fig.org/psr/psr-4/

    The fully qualified class name MUST have a top-level namespace name, also known as a “vendor namespace”.

    Ok, you can say "SqlParser" is the vendor... a way to circumvent PSR-4 (as the project SubNamespaceName is not mandatory.. one reason why I dislike this PSR). And SqlParser could be a bit too generic and may create conflict.

    Proposal: use PhpMyAdmin\SqlParser

    I understand this is only doable as part of a new major version, because of BC break.

    enhancement 
    opened by remicollet 10
  • Better Formatter tests

    Better Formatter tests

    Writing tests this way can be harden, but you can be sure that your feature/fix for an formatter type will not impact on any other formatter type.

    WDYT? If you think that can be useful I'll continue to write tests for the remaining tests cases.

    opened by bigfoot90 10
  • Fixing parser errors when adding columns with SET type

    Fixing parser errors when adding columns with SET type

    Hi, This PR should fix https://github.com/phpmyadmin/sql-parser/issues/168 and the issues shown https://github.com/phpmyadmin/sql-parser/pull/337

    I will clarify the changes in a review.

    Testing in PMA too.

    opened by iifawzi 9
  • Bad procedure body

    Bad procedure body

     CREATE DEFINER=`root`@`%` PROCEDURE `test2`(IN `_var` INT) NOT DETERMINISTIC NO SQL SQL SECURITY INVOKER NO SQL SQL SECURITY INVOKER SELECT _var
    

    The detected is

    NO SQL
        SQL SECURITY INVOKER
    SELECT _var
    

    It should be

    SELECT _var
    

    Ref: https://github.com/phpmyadmin/phpmyadmin/issues/15991

    bug 
    opened by williamdes 9
  • array_key_exists warning when parsing a

    array_key_exists warning when parsing a "DEFAULT FALSE" token

    PHP Warning:  array_key_exists(): The first argument should be either a string or an integer in /var/www/html/vendor/phpmyadmin/sql-parser/src/Components/AlterOperation.php on line 286
    

    A dump inside AlterOperation.php gives me the following result: image

    I don't have any idea if the value attribute should be a boolean in this case, so I'm not starting a PR right now. I don't know if the correct solution would be to cast to string on the array_key_exists itself, or to save the value attribute as a string instead of a boolean...

    bug 
    opened by devnix 8
  • WITH keyword

    WITH keyword

    The WITH keyword is now supported for CTEs starting with MariaDB 10.2.1 and MySQL 8.0.

    See https://github.com/phpmyadmin/phpmyadmin/issues/13616

    ./lint-query --query "WITH t as (select a from t1 where b >= 'c') 
    >   select * from t2,t where t2.c=t.a;"
    #1: Unrecognized statement type. (near "WITH" at position 0)
    
    bug 
    opened by ibennetch 8
  • Parser mistakes with comments

    Parser mistakes with comments

    The parser may not well deal with the comments. Here is an example, as it treat -- as a part of table alias.

    Give sql as

    SELECT  * FROM ecshop.ecs_order_info 
    -- LIMIT 0, 30 
    --
    

    process by PhpMyAdmin\SqlParser\Parser

    object(PhpMyAdmin\SqlParser\Statements\SelectStatement)#28 (16) {
      ["expr"]=>
      array(1) {
        [0]=>
        object(PhpMyAdmin\SqlParser\Components\Expression)#13 (7) {
          ["database"]=>
          NULL
          ["table"]=>
          NULL
          ["column"]=>
          NULL
          ["expr"]=>
          string(1) "*"
          ["alias"]=>
          NULL
          ["function"]=>
          NULL
          ["subquery"]=>
          NULL
        }
      }
      ["from"]=>
      array(1) {
        [0]=>
        object(PhpMyAdmin\SqlParser\Components\Expression)#11 (7) {
          ["database"]=>
          string(6) "ecshop"
          ["table"]=>
          string(14) "ecs_order_info"
          ["column"]=>
          NULL
          ["expr"]=>
          string(23) "ecshop.ecs_order_info--"
          ["alias"]=>
          NULL
          ["function"]=>
          NULL
          ["subquery"]=>
          NULL
        }
      }
      ["partition"]=>
      NULL
      ["where"]=>
      NULL
      ["group"]=>
      NULL
      ["having"]=>
      NULL
      ["order"]=>
      NULL
      ["limit"]=>
      object(PhpMyAdmin\SqlParser\Components\Limit)#27 (2) {
        ["offset"]=>
        int(0)
        ["rowCount"]=>
        int(30)
      }
      ["procedure"]=>
      NULL
      ["into"]=>
      NULL
      ["join"]=>
      NULL
      ["union"]=>
      array(0) {
      }
      ["end_options"]=>
      NULL
      ["options"]=>
      object(PhpMyAdmin\SqlParser\Components\OptionsArray)#30 (1) {
        ["options"]=>
        array(0) {
        }
      }
      ["first"]=>
      int(0)
      ["last"]=>
      int(12)
    }
    

    and rebuild after ensuring the limit expression is appended (by check the statement->limit property, and add it if lack), would get

    SELECT  * FROM ecshop.ecs_order_info-- LIMIT 0, 30 
    
    bug 
    opened by sinri 8
  • Exporting table structure with COMPRESSED column - corrupt SQL

    Exporting table structure with COMPRESSED column - corrupt SQL

    As per phpmyadmin/phpmyadmin#14956, if we create a Table that contains one column that is "TEXT COMPRESSED", in MariaDB, and then we do an Export, the CREATE TABLE statement will be corrupt, starting from the compressed column:

    image

    And the "ALTER TABLE ADD KEY" statement that follows also didn't appear.

    bug 
    opened by nunoperalta 7
  • Try to fix #404. Miss some unit tests.

    Try to fix #404. Miss some unit tests.

    Hello all.

    I'm working IRL with @SanaRebhi and we tried to make a proposal in order to solve this topic.

    I made some manual tests and it looks like it's OK, but I want to go deeper and add unit tests also to cover (almost) all test cases about ALTER EVENT statements, which I don't have time right now.

    Current unit-test suite is passing (with 2 ignored test-cases out of this range) locally.

    Please feel free to tell me if this approch is a good one and I can continue to write tests or if you have another way in mind to manage it.

    Thanks a lot.

    Ref: #404

    opened by niconoe- 3
  • Exporting procedures with 'MODIFIES SQL DATA' generates a warning in OptionsArray.php

    Exporting procedures with 'MODIFIES SQL DATA' generates a warning in OptionsArray.php

    Describe the bug

    When you export a database with the 'Add CREATE PROCEDURE / FUNCTION / EVENT statement' option enabled, and the procedure definition includes 'MODIFIES SQL DATA', the parser generates the following message:

    Warning in ./vendor/phpmyadmin/sql-parser/src/Components/OptionsArray.php#306
    Undefined array key "value"
    

    Dumping the value of $option just before that shows the following as the cause of the message:

    Array
    (   
        [name] => MODIFIES
        [equals] =>
        [expr] =>
    )
    

    To Reproduce

    Create a procedure with 'MODIFIES SQL DATA' as the SQL data access option. Click the Export tab for the database with said procedure. Perform a custom export with the 'Add CREATE PROCEDURE / FUNCTION / EVENT statement' See the warning and backtrace.

    Expected behavior

    No warning messages during the export.

    Screenshots

    Here's the full backtrace:

    Warning in ./vendor/phpmyadmin/sql-parser/src/Components/OptionsArray.php#306
    Undefined array key "value"
    
    Backtrace
    
    CreateStatement.php#491: PhpMyAdmin\SqlParser\Components\OptionsArray::build()
    ExportSql.php#2814: PhpMyAdmin\SqlParser\Statements\CreateStatement->build()
    ExportSql.php#558: PhpMyAdmin\Plugins\Export\ExportSql->replaceWithAliases(
    string 'CREATE DEFINER=`root`@`localhost` PROCEDURE `split_string`(IN `x` VARCHAR(255), IN `delim` VARCHAR(12), IN `id` CHAR(36)) MODIFIES SQL DATA DETERMINISTIC BEGIN SET @valcount = substrCount(x,delim)+1; SET @vl = 0; CREATE TEMPORARY TABLE IF NOT EXISTS splitResultsTemp (uuid char(36), split_value varchar(255)) ENGINE=MEMORY; WHILE (@vl < @valcount) DO SET @val = stringSplit(x,delim,@vl+1); INSERT INTO splitResultsTemp (uuid, split_value) VALUES (id, @val); SET @vl = @vl + 1; END WHILE; END',
    array,
    string 'ftp_accounts',
    string '',
    boolean false,
    )
    ExportSql.php#620: PhpMyAdmin\Plugins\Export\ExportSql->exportRoutineSQL(
    string 'ftp_accounts',
    array,
    string 'PROCEDURE',
    string 'Procedures',
    array,
    string '$$',
    )
    Export.php#742: PhpMyAdmin\Plugins\Export\ExportSql->exportRoutines(
    string 'ftp_accounts',
    array,
    )
    ExportController.php#548: PhpMyAdmin\Export->exportDatabase(
    string 'ftp_accounts',
    array,
    string 'structure_and_data',
    array,
    array,
    ,
    string ' ',
    string 'index.php?route=/database/export&db=ftp_accounts',
    string 'database',
    boolean true,
    boolean true,
    boolean true,
    boolean true,
    array,
    string '',
    )
    Routing.php#192: PhpMyAdmin\Controllers\Export\ExportController->__invoke(
    ,
    array,
    )
    index.php#43: PhpMyAdmin\Routing::callControllerForRoute(
    ,
    string '/export',
    ,
    ,
    )
    

    Server configuration

    • Operating system: RHEL 9
    • Web server: Apache httpd 2.4.53-7.el9
    • Database version: mariadb-server 10.5.16-2.el9_0
    • PHP version: 8.1.8-1module+el91.0+15877+c3862210
    • phpMyAdmin version: 5.2.0-1.el9.remi

    Client configuration

    • Browser: Firefox 108.0.1
    • Operating system: Windows 10 Enterprise 20H2

    Additional context

    This happens with multiple databases, each of witch have a stored procedure that modifies SQL data.

    bug 
    opened by offsides 8
  • 'ALTER TABLE ... RENAME INDEX ...' statement not parsed correctly

    'ALTER TABLE ... RENAME INDEX ...' statement not parsed correctly

    Hello,

    The following SQL statement is not parsed entirely by SQL Parser

    ALTER TABLE `transactions` RENAME INDEX `fk_transactions_catalog_entries1_idx` TO `fk_transactions_catalog_entries2_idx`
    

    It fails with the following message:

    Missing comma before start of a new alter operation. (near TO)

    The same happens in PhpMyAdmin v5.2.0 as well:

    image

    Do you know what could be happening?

    Thanks a lot!

    bug 
    opened by nachopitt 1
  • "ALTER EVENT" is not recognized by the SQL parser

    It seems that the latest release of sql-parser (5.6.0) does not support "ALTER EVENTS" yet. The AlterOperation component needs to be updated in order to add all the options for the EVENT. Any plans to handle this kind of statements please?

    bug enhancement 
    opened by SanaRebhi 2
  • Hard to find package

    Hard to find package

    I was looking for a SQL parser written in Php a few weeks ago and I searched on google: "SQL tokenizer in PHP" etc, but there was no clue of this gem out there and I was totally disappointed.

    I eventually stumbled upon this by pure chance while I was looking in PHPMyAdmin composer.json file by accident.

    You may ask and answer some questions about its functionality in stack overflow and tag it better on Github or packagist.org.

    Good luck and thanks.

    enhancement 
    opened by imanghafoori1 4
  • The license of this package is 'viral'

    The license of this package is 'viral'

    This package has a so called Viral license (GPL-2.0-or-later). Because of the 'viral' aspect of this, AFAIK this means that we are actually unable to use it in a closed source project. Would it be possible to change this license to a non-viral one?

    Related to https://github.com/nunomaduro/larastan/issues/1373

    opened by gisostallenberg 1
Releases(5.6.0)
Owner
phpMyAdmin
We're building phpMyAdmin, the most used MySQL management tool.
phpMyAdmin
Tiny php mysql lib (PDO-based) with handy fetch/update functionality, supports both SQL and parametric queries

Micro PHP mysql lib (~ 200 lines of code) with ultra powerful CRUD for faster than ever development: parametric fetch/insert/update/delete (based on a

Mr Crypster 18 Dec 10, 2022
The Enobrev\ORM library is a small framework of classes meant to be used for simply mapping a mysql database to PHP classes, and for creating simply SQL statements using those classes.

The Enobrev\ORM library is a small framework of classes meant to be used for simply mapping a mysql database to PHP classes, and for creating simply SQL statements using those classes.

Mark Armendariz 0 Jan 7, 2022
API abstracting communication with SQL providers (eg: MySQL) on top of PDO inspired by Java JDBC

SQL Data Access API Table of contents: About Configuration Execution Installation Unit Tests Examples Reference Guide About This API is a ultra light

Lucian Gabriel Popescu 0 Jan 9, 2022
A php securised login system, using Hash, Salt and prevent from SQL Injections

A Basic Secure Login Implementation Hashed & Salted password ( only hashed in ShA-512 for now ) No SQL injection possible Prevent XSS attacks from the

Yohann Boniface 1 Mar 6, 2022
A Laravel package to output a specific sql to your favourite debugging tool. The supported log output is Laravel Telescope, Laravel Log, Ray, Clockwork, Laravel Debugbar and your browser.

Laravel showsql A Laravel package to output a specific sql to your favourite debugging tool, your browser or your log file. Use case You often want to

Dieter Coopman 196 Dec 28, 2022
SQL database access through PDO.

Aura.Sql Provides an extension to the native PDO along with a profiler and connection locator. Because ExtendedPdo is an extension of the native PDO,

Aura for PHP 533 Dec 30, 2022
ATK Data - Data Access Framework for high-latency databases (Cloud SQL/NoSQL).

ATK Data - Data Model Abstraction for Agile Toolkit Agile Toolkit is a Low Code framework written in PHP. Agile UI implement server side rendering eng

Agile Toolkit 257 Dec 29, 2022
A SQL query builder with zero dependencies

Latitude Query Builder A SQL query builder with zero dependencies. Attempts to be PSR-1, PSR-2, and PSR-4 compliant. Install composer require latitude

Woody Gilk 618 Dec 30, 2022
SQL to Laravel Query Builder

Marwan - SQL To Laravel Builder SQL to Laravel Query Builder, A Converter written in PHP Features Converts SQL Queries to Laravel Query Builder. Assis

Rexhep Shijaku 162 Dec 19, 2022
Extract SQL statements from migrations

This is my package MigrationToSql To install: composer require bcleverly/migrationtosql --dev This repo is here to help you extract the SQL queries fr

Ben 4 Apr 15, 2022
A minimalistic implementation of asynchronous SQL for PHP.

libSQL A minimalistic implementation of asynchronous SQL for PHP. Installation via DEVirion Install the DEVirion plugin and start your server. This wi

null 10 Dec 7, 2022
TO DO LIST WITH LOGIN AND SIGN UP and LOGOUT using PHP and MySQL please do edit the _dbconnect.php before viewing the website.

TO-DO-LIST-WITH-LOGIN-AND-SIGN-UP TO DO LIST WITH LOGIN AND SIGN UP and LOGOUT using PHP and MySQL please do edit the _dbconnect.php before viewing th

Aniket Singh 2 Sep 28, 2021
phpMyFAQ - Open Source FAQ web application for PHP and MySQL, PostgreSQL and other databases

phpMyFAQ 3.1 What is phpMyFAQ? phpMyFAQ is a multilingual, completely database-driven FAQ-system. It supports various databases to store all data, PHP

Thorsten Rinne 547 Dec 27, 2022
A simple and extensible fixture loader for PHP 7.3+, supporting SQLite and MySQL

Flowder Flowder is a (really) simple fixture loader for PHP 7.3+, supporting SQLite and MySQL. Using Flowder in PHP 7.2 or below? Try version 1 instea

Joe Haines 6 Jan 17, 2021
Connect and work with MySQL/MariaDB database through MySQLi in PHP. This is an introductory project, If you need a simple and straightforward example that takes you straight to the point, you can check out these examples.

First MySQLi PHP Connect and work with MySQL/MariaDB database through MySQLi in PHP. The above exercises are designed for students. This is an introdu

Max Base 4 Feb 22, 2022
Staggered import of large and very large MySQL Dumps even through the web servers with hard runtime limit and those in safe mode.

Staggered import of large and very large MySQL Dumps (like phpMyAdmin dumps) even through the web servers with hard runtime limit and those in safe mode. | Persian Translation Version

Amir Shokri 5 Jan 8, 2022
A web interface for MySQL and MariaDB

phpMyAdmin A web interface for MySQL and MariaDB. https://www.phpmyadmin.net/ Code status Download You can get the newest release at https://www.phpmy

phpMyAdmin 6.4k Jan 5, 2023
A simple PHP and MySQL based internet forum that displays the messages in classical threaded view (tree structure)

my little forum my little forum is a simple PHP and MySQL based internet forum that displays the messages in classical threaded view (tree structure).

Mark Hoschek 97 Dec 29, 2022
A Symfony application for managing and automating regular backups of MySQL databases.

DbSaver DbSaver is an application written by Bastien LOUGHIN allowing you to make automatic daily backups (and manual backups) for your MySQL database

Bastien 35 Nov 11, 2022