A lightweight php class for formatting sql statements. Handles automatic indentation and syntax highlighting.

Overview

SqlFormatter

A lightweight php package for formatting sql statements.

It can automatically indent and add line breaks in addition to syntax highlighting.

History

This package is a fork from https://github.com/jdorn/sql-formatter Here is what the original History section says:

I found myself having to debug auto-generated SQL statements all the time and wanted some way to easily output formatted HTML without having to include a huge library or copy and paste into online formatters.

I was originally planning to extract the formatting code from PhpMyAdmin, but that was 10,000+ lines of code and used global variables.

I saw that other people had the same problem and used Stack Overflow user losif's answer as a starting point. http://stackoverflow.com/a/3924147

― @jdorn

Usage

The SqlFormatter class has a method format which takes an SQL string as input and returns a formatted block.

Sample usage:

= NOW()) ) GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10"; echo (new SqlFormatter())->format($query); ">

require_once 'vendor/autoload.php';

use Doctrine\SqlFormatter\SqlFormatter;

$query = "SELECT count(*),`Column1`,`Testing`, `Testing Three` FROM `Table1`
    WHERE Column1 = 'testing' AND ( (`Column2` = `Column3` OR Column4 >= NOW()) )
    GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10";

echo (new SqlFormatter())->format($query);

Output:

formatted output with HTML Highlight

When you run php under cli and instantiated SqlFormatter without argument, highlighted with CliHighlighter.

SqlFormatter constructor takes Highlighter implementations. HtmlHighlighter etc.

Formatting Only

If you don't want syntax highlighting and only want the indentations and line breaks, pass in a NullHighlighter instance as the second parameter.

This is useful for outputting to error logs or other non-html formats.



use Doctrine\SqlFormatter\NullHighlighter;
use Doctrine\SqlFormatter\SqlFormatter;

echo (new SqlFormatter(new NullHighlighter()))->format($query);

Output:

SELECT
  count(*),
  `Column1`,
  `Testing`,
  `Testing Three`
FROM
  `Table1`
WHERE
  Column1 = 'testing'
  AND (
    (
      `Column2` = `Column3`
      OR Column4 >= NOW()
    )
  )
GROUP BY
  Column1
ORDER BY
  Column3 DESC
LIMIT
  5, 10

Syntax Highlighting Only

There is a separate method highlight that preserves all original whitespace and just adds syntax highlighting.

This is useful for sql that is already well formatted and just needs to be a little easier to read.


echo (new SqlFormatter())->highlight($query);

Output:

HTML Highlight output

Compress Query

The compress method removes all comments and compresses whitespace.

This is useful for outputting queries that can be copy pasted to the command line easily.

-- This is a comment
    SELECT
    /* This is another comment
    On more than one line */
    Id #This is one final comment
    as temp, DateCreated as Created FROM MyTable;
echo (new SqlFormatter())->compress($query);

Output:

SELECT Id as temp, DateCreated as Created FROM MyTable;
Comments
  • Add support for common table expressions and window functions

    Add support for common table expressions and window functions

    Now to the main show, this adds support for common table expressions and window functions.

    I would have liked to add additional nesting on new lines for the FILTER() and OVER() clauses, eg:

    GROUP_CONCAT(b, '.')
      FILTER (
        WHERE
          c != 'two'
      )
      OVER (
        ORDER BY
          a
      )
      AS filtered,
    

    however without a larger rewrite of the formatter, all I could come up with was pretty hack-ish, and way too much tied to this specific syntax, so for now it would still be a bit squished.

    Resolves #37

    enhancement 
    opened by ndm2 6
  • Adding many options as an or'ed list of flags

    Adding many options as an or'ed list of flags

    Hello.

    Why not adding an option to all suitable methods which would be an integer defaulting to zero, able to receive an or'ed list of flags, each ones defining an option (chosen among a list provided as define('')'s constants) ? Many options could be defined there :

    • Convert keywords to uppercases (or to lowercases)
    • Convert function names to uppercases (or to lowercases)
    • Add back-ticks wherever suitable
    • Add 'AS' keyword before aliases if not already there
    • Add line numbering to syntax highlighting
    • Etc, etc

    This would be largely open to future as an integer could potentially contain up to 32 options.

    opened by GingkoFr 5
  • Improve formatting of MODIFY, CHANGE and AFTER

    Improve formatting of MODIFY, CHANGE and AFTER

    I found some formatting problems in the current version 1.1.0.

    1. MODIFY

    Input

    ALTER TABLE `table` MODIFY `id` INT(11) UNSIGNED NOT NULL
    

    Result

    ALTER TABLE
      `table` MODIFY `id` INT(11) UNSIGNED NOT NULL
    

    Expected result

    ALTER TABLE
      `table`
    MODIFY
      `id` INT(11) UNSIGNED NOT NULL
    

    2. CHANGE

    Input

    ALTER TABLE `table` CHANGE `id` `_id` BIGINT(20) UNSIGNED NULL
    

    Result

    ALTER TABLE
      `table` CHANGE `id` `_id` BIGINT(20) UNSIGNED NULL
    

    Expected result

    ALTER TABLE
      `table`
    CHANGE
      `id` `_id` BIGINT(20) UNSIGNED NULL
    

    3. AFTER

    Input

    ALTER TABLE `table` MODIFY `id` INT(11) UNSIGNED NOT NULL FIRST, CHANGE `name` `firstname` VARCHAR(20) COLLATE 'utf8mb4_unicode_ci' NOT NULL AFTER `id`, CHANGE `name2` `lastname` VARCHAR(30) COLLATE 'utf8mb4_unicode_ci' NOT NULL AFTER `firstname`, ADD `city` VARCHAR(20) COLLATE 'utf8mb4_unicode_ci' AFTER `lastname`
    

    Result

    ALTER TABLE
      `table` MODIFY `id` INT(11) UNSIGNED NOT NULL FIRST,
      CHANGE `name` `firstname` VARCHAR(20) COLLATE 'utf8mb4_unicode_ci' NOT NULL
    AFTER
      `id`,
      CHANGE `name2` `lastname` VARCHAR(30) COLLATE 'utf8mb4_unicode_ci' NOT NULL
    AFTER
      `firstname`,
    ADD
      `city` VARCHAR(20) COLLATE 'utf8mb4_unicode_ci'
    AFTER
      `lastname`
    

    Expected result

    ALTER TABLE
      `table`
    MODIFY
      `id` INT(11) UNSIGNED NOT NULL FIRST,
    CHANGE
      `name` `firstname` VARCHAR(20) COLLATE 'utf8mb4_unicode_ci' NOT NULL AFTER `id`,
    CHANGE
      `name2` `lastname` VARCHAR(30) COLLATE 'utf8mb4_unicode_ci' NOT NULL AFTER `firstname`,
    ADD
      `city` VARCHAR(20) COLLATE 'utf8mb4_unicode_ci' AFTER `lastname`
    
    opened by MaximilianKresse 4
  • Missing tags?

    Missing tags?

    https://packagist.org/packages/doctrine/sql-formatter shows 1.1.0 and 1.1.1 but I don't see any sign of them on https://github.com/doctrine/sql-formatter/tags or https://github.com/doctrine/sql-formatter/releases

    Similarly https://github.com/doctrine/sql-formatter/tree/1.1.0 and https://github.com/doctrine/sql-formatter/tree/1.1.1 give a 404

    opened by reedy 4
  • Use generators

    Use generators

    My goal with the second commit was to use generators for getFilteredTokens, and then I realized it would not be possible: there are lookaheads up to 250 tokens ahead to decide whether to stay inline or to add linebreaks. It made me move a lot of logic to the value objects though, and get rid of the $indexedTokens ugly array.

    opened by greg0ire 4
  • Add missing comparisons.

    Add missing comparisons.

    #45 added a missing test for a fix, but only added a comparison for compression, the missing comparisons in the other files will cause newly added comparisons to fail, as they will be compared to the wrong SQL.

    opened by ndm2 2
  • Use generators

    Use generators

    The program was written when they did not exist, and it acts on text in a very streamy way (or at least, should). Let's see if we can leverage generators to improve it, be it memory-wise, or just readability-wise: maybe we could get rid of most of the $return .= 'some string' concatenations.

    opened by greg0ire 2
  • Set allow-plugins for Composer 2.2

    Set allow-plugins for Composer 2.2

    This new configuration has been introduced with Composer 2.2: https://github.com/composer/composer/releases/tag/2.2.0-RC1

    See also the documentation: https://getcomposer.org/doc/06-config.md#allow-plugins

    opened by villfa 1
  • New option to make

    New option to make "AS" aliases aligned vertically

    Hi, it's often more readable when selected column aliases are aligned vertically. Instead of this:

    SELECT   foo as one   foofoo as two   foofoofoo as three

    we can have this:

    SELECT   foo           as one   foofoo      as two   foofoofoo as three

    Configuration option for that would be nice.

    opened by javaDeveloperKid 0
  • Option to force uppercase SQL keywords

    Option to force uppercase SQL keywords

    This adds a new optional third parameter to the format method, $forceUppercase which defaults to false to maintain backwards compatibility.

    When passed as true, all keywords will be uppercased.

    There is a new test written in for this functionality that passes.

    Fixes: https://github.com/doctrine/sql-formatter/issues/32. Implementation abstracted from the original PR against the forked source: https://github.com/jdorn/sql-formatter/pull/86

    opened by othyn 0
  • [Question] PostgreSQL Cast Operator

    [Question] PostgreSQL Cast Operator

    I noticed the PostgreSQL cast shortcut is incorrectly split, for example 123::bigint becomes 123: :bigint.

    I can look at making a PR to support this, but first I wanted to check if there was interest in this tool supporting platform specific syntax... ?

    opened by rodnaph 2
  • SQLite format doesn't always split on comma

    SQLite format doesn't always split on comma

    In this example, why doesn't ct_tag_id end up on a new row?

    Given

    CREATE TABLE /*_*/change_tag (ct_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, ct_rc_id INTEGER UNSIGNED DEFAULT NULL, ct_log_id INTEGER UNSIGNED DEFAULT NULL, ct_rev_id INTEGER U>
    
    CREATE UNIQUE INDEX change_tag_rc_tag_id ON /*_*/change_tag (ct_rc_id, ct_tag_id);
    
    CREATE UNIQUE INDEX change_tag_log_tag_id ON /*_*/change_tag (ct_log_id, ct_tag_id);
    
    CREATE UNIQUE INDEX change_tag_rev_tag_id ON /*_*/change_tag (ct_rev_id, ct_tag_id);
    

    After running ( new SqlFormatter( new NullHighlighter() ) )->format( $sql ) we end up with

    CREATE TABLE
    /*_*/
    change_tag (
      ct_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
      ct_rc_id INTEGER UNSIGNED DEFAULT NULL,
      ct_log_id INTEGER UNSIGNED DEFAULT NULL,
      ct_rev_id INTEGER UNSIGNED DEFAULT NULL,
      ct_params BLOB DEFAULT NULL, ct_tag_id INTEGER UNSIGNED NOT NULL
    ); CREATE UNIQUE INDEX change_tag_rc_tag_id ON
    /*_*/
    change_tag (ct_rc_id, ct_tag_id); CREATE UNIQUE INDEX change_tag_log_tag_id ON
    /*_*/
    change_tag (ct_log_id, ct_tag_id); CREATE UNIQUE INDEX change_tag_rev_tag_id ON
    /*_*/
    change_tag (ct_rev_id, ct_tag_id); CREATE INDEX change_tag_tag_id_id ON
    /*_*/
    change_tag (
      ct_tag_id, ct_rc_id, ct_rev_id, ct_log_id
    );
    

    We should end up with (ignoring #53)

    CREATE TABLE
    /*_*/
    change_tag (
      ct_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
      ct_rc_id INTEGER UNSIGNED DEFAULT NULL,
      ct_log_id INTEGER UNSIGNED DEFAULT NULL,
      ct_rev_id INTEGER UNSIGNED DEFAULT NULL,
      ct_params BLOB DEFAULT NULL,
      ct_tag_id INTEGER UNSIGNED NOT NULL
    ); CREATE UNIQUE INDEX change_tag_rc_tag_id ON
    /*_*/
    change_tag (ct_rc_id, ct_tag_id); CREATE UNIQUE INDEX change_tag_log_tag_id ON
    /*_*/
    change_tag (ct_log_id, ct_tag_id); CREATE UNIQUE INDEX change_tag_rev_tag_id ON
    /*_*/
    change_tag (ct_rev_id, ct_tag_id); CREATE INDEX change_tag_tag_id_id ON
    /*_*/
    change_tag (
      ct_tag_id, ct_rc_id, ct_rev_id, ct_log_id
    );
    
    opened by reedy 0
  • Extra newlines between CREATE statements

    Extra newlines between CREATE statements

    Given this input (as output from Doctrine, with trailing ; and newlines added)

    CREATE TABLE /*_*/actor (actor_id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, actor_user INT UNSIGNED DEFAULT NULL, actor_name VARBINARY(255) NOT NULL, UNIQUE INDEX actor_user (actor_user), UNIQUE INDEX actor_name (actor_name), PRIMARY KEY(actor_id)) /*$wgDBTableOptions*/;
    
    CREATE TABLE /*_*/user_former_groups (ufg_user INT UNSIGNED DEFAULT 0 NOT NULL, ufg_group VARBINARY(255) DEFAULT '' NOT NULL, PRIMARY KEY(ufg_user, ufg_group)) /*$wgDBTableOptions*/;
    

    Calling ( new SqlFormatter( new NullHighlighter() ) )->format( $schema ); gives

    CREATE TABLE
    /*_*/
    actor (
      actor_id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
      actor_user INT UNSIGNED DEFAULT NULL,
      actor_name VARBINARY(255) NOT NULL,
      UNIQUE INDEX actor_user (actor_user),
      UNIQUE INDEX actor_name (actor_name),
      PRIMARY KEY(actor_id)
    )
    /*$wgDBTableOptions*/
    ; CREATE TABLE
    /*_*/
    user_former_groups (
      ufg_user INT UNSIGNED DEFAULT 0 NOT NULL,
      ufg_group VARBINARY(255) DEFAULT '' NOT NULL,
      PRIMARY KEY(ufg_user, ufg_group)
    )
    /*$wgDBTableOptions*/
    ;
    

    Is it possible to add some more newlines? https://github.com/doctrine/sql-formatter/blob/1.0.x/src/SqlFormatter.php#L49 obviously doesn't take any options

    Similar for some postgres:

    CREATE TABLE /*_*/actor (actor_id BIGSERIAL NOT NULL, actor_user INT DEFAULT NULL, actor_name BYTEA NOT NULL, PRIMARY KEY(actor_id));
    
    CREATE UNIQUE INDEX actor_user ON /*_*/actor (actor_user);
    
    CREATE UNIQUE INDEX actor_name ON /*_*/actor (actor_name);
    
    CREATE TABLE /*_*/user_former_groups (ufg_user INT DEFAULT 0 NOT NULL, ufg_group BYTEA DEFAULT '' NOT NULL, PRIMARY KEY(ufg_user, ufg_group));
    

    to

    CREATE TABLE
    /*_*/
    actor (
      actor_id BIGSERIAL NOT NULL,
      actor_user INT DEFAULT NULL,
      actor_name BYTEA NOT NULL,
      PRIMARY KEY(actor_id)
    ); CREATE UNIQUE INDEX actor_user ON
    /*_*/
    actor (actor_user); CREATE UNIQUE INDEX actor_name ON
    /*_*/
    actor (actor_name); CREATE TABLE
    /*_*/
    user_former_groups (
      ufg_user INT DEFAULT 0 NOT NULL,
      ufg_group BYTEA DEFAULT '' NOT NULL,
      PRIMARY KEY(ufg_user, ufg_group)
    );
    
    opened by reedy 2
Releases(1.1.3)
Owner
Doctrine
The Doctrine Project is the home to several PHP libraries primarily focused on database storage and object mapping.
Doctrine
Spf codemirror - CodeMirror syntax-highlighting for Textpattern

spf_codemirror I’m no longer able to develop this plugin due to ill health. If anyone would like to take over, message me, and I’ll transfer the sourc

Gustavo Reis 6 Mar 16, 2018
Text formatting for humans.

Deutsch English Svenska Markdown 0.8.22 Text formatting for humans. How to format text Markdown is a practical way to edit web pages. Write text like

Anna 2 Nov 3, 2022
A lightweight SQL generation library.

Atlas A lightweight SQL builder library without any query execution or database connection requirements. The primary goals of this package are: To pro

RebelCode 1 May 11, 2022
Small utility library that handles metadata minification and expansion.

composer/metadata-minifier Small utility library that handles metadata minification and expansion.

Composer 134 Dec 26, 2022
A simple mini pos that handles managing product data's and product categories

What is CodeIgniter CodeIgniter is an Application Development Framework - a toolkit - for people who build web sites using PHP. Its goal is to enable

Mahendra Dwi Purwanto 0 Dec 26, 2021
Handles ActiveRecord's attribute translations

TranslateableBehavior for Yii2 This behavior has been inspired by the great work of Mikehaertl's Translatable Behavior for Yii 1.*. It eases the trans

2amigOS! Consulting Group 67 May 21, 2022
Exploiting and fixing security vulnerabilities of an old version of E-Class. Project implemented as part of the class YS13 Cyber-Security.

Open eClass 2.3 Development of XSS, CSRF, SQLi, RFI attacks/defences of an older,vulnerable version of eclass. Project implemented as part of the clas

Aristi_Papastavrou 11 Apr 23, 2022
This module integrates Silverstripe CMS with Google Translate API and then allows content editors to use automatic translation for every translatable field.

Autotranslate This module integrates Silverstripe CMS with Google Translate API and then allows content editors to use automatic translation for every

null 4 Jan 3, 2022
An auto software that collects, scans and sends automatic instagram users

Instagram Advanced User Finder V1.0.0 With this PHP script, you can find users on Instagram and message them. Feedback Türkçe Get Key every week, you

Yasin 70 Jan 4, 2023
FUGIO: Automatic Exploit Generation for PHP Object Injection Vulnerabilities

FUGIO FUGIO is the first automatic exploit generation (AEG) tool for PHP object injection (POI) vulnerabilities. When exploiting a POI vulnerability,

KAIST Web Security and Privacy Lab 53 Dec 23, 2022
PHP implementation of Rapid Automatic Keyword Exraction algorithm (RAKE) for extracting multi-word phrases from text

PHP implementation of Rapid Automatic Keyword Exraction algorithm (RAKE) for extracting multi-word phrases from text.

Assisted Mindfulness 7 Oct 19, 2022
A simple PHP package for sending messages to Slack, with a focus on ease of use and elegant syntax.

Slack for PHP A simple PHP package for sending messages to Slack with incoming webhooks, focussed on ease-of-use and elegant syntax. Note: this packag

Regan McEntyre 1.2k Oct 29, 2022
PHP Parallel Lint - This tool check syntax of PHP files faster than serial check with fancier output

PHP Parallel Lint This application checks syntax of PHP files in parallel. It can output in plain text, colored text, json and checksyntax formats. Ad

PHP Parallel lint 156 Apr 24, 2022
A Magento 1.x module which facilitates automatic purging of static assets from HTTP caches such as browser cache, CDN, Varnish, etc using best practices outlined within the HTML5 boilerplate community.

Magento Cachebuster Cachebuster is a Magento module which facilitates automatic purging of static assets from HTTP caches such as browser cache, CDN,

Gordon Knoppe 129 Apr 1, 2022
Provides automatic recaching of product URLs within Prerender.io

magento2-prerender-io Provides integration between Magento 2 and Prerender.io, giving the ability for product pages to be automatically recached when

Aligent 2 Jun 28, 2022
DBML parser for PHP8. It's a PHP parser for DBML syntax.

DBML parser written on PHP8 DBML (database markup language) is a simple, readable DSL language designed to define database structures. This page outli

Pavel Buchnev 32 Dec 29, 2022
CPAY is a sdk that encapsulates the Orange Money api with an intuitive syntax allowing you to integrate the Orange Money payment into your PHP project.

CPAY CHOCO PAY is a sdk that encapsulates the Orange Money api with an intuitive syntax allowing you to integrate the Orange Money payment into your P

faso-dev 1 Oct 26, 2022
This tool check syntax of PHP files faster than serial check with fancier output.

PHP Parallel Lint This application checks syntax of PHP files in parallel. It can output in plain text, colored text, json and checksyntax formats. Ad

PHP Parallel lint 202 Dec 22, 2022
Kiaan PHP is a web application framework with expressive, elegant syntax.

About Kiaan framework Kiaan is a web application framework for PHP. Kiaan is easy, flexible and professional. Documentation You can learn kiaan with t

Kiaan 30 Oct 17, 2022