Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
A Python based SQL formatter
Via pip
pip install sql-formatter
or via conda
conda install -c pablormira sql_formatter
Format your SQL files via the command line
sql-formatter sql_file.sql sql_file2.sql
You can also format all your SQL-files via
sql-formatter *.sql
To format all your SQL files recursively use
sql-formatter -r "*.sql"
The sql_formatter
will try to truncate too long lines in the SELECT
clause for either
in
with many elementsThe default maximum line length is 82 after line stripping.
You can control the maximum length line using e.g.
sql-formatter sql_file.sql --max-line-length=50
pre-commit
pre-commit is a nice development tool to automatize the binding of pre-commit hooks. After installation and configuration pre-commit
will run your hooks before you commit any change.
To add sql-formatter
as a hook to your pre-commit
configuration to format your SQL files before commit, just add the following lines to your .pre-commit-config.yaml
:
repos:
- repo: https://github.com/PabloRMira/sql_formatter
rev: master
hooks:
- id: sql_formatter
If you want to install sql-formatter
locally and use that instead of using pre-commit
's default environment, set repo: local
in your .pre-commit-config.yaml
file:
repos:
- repo: local
hooks:
- id: sql_formatter
name: SQL formatter
language: system
entry: sql-formatter
files: \.sql$
or
repos:
- repo: local
hooks:
- id: sql_formatter
name: SQL formatter
language: system
entry: sql-formatter --max-line-length=50
files: \.sql$
for a custom maximum line length truncation of e.g. 50
To exemplify the formatting let's say you have a SQL query like this
example_sql = """
create or replace table mytable as -- mytable example
seLecT a.asdf, b.qwer, -- some comment here
c.asdf, -- some comment there
b.asdf2 frOm table1 as a leFt join
table2 as b -- and here a comment
on a.asdf = b.asdf -- join this way
inner join table3 as c
on a.asdf=c.asdf
whEre a.asdf= 1 -- comment this
anD b.qwer =2 and a.asdf<=1 --comment that
or b.qwer>=5
groUp by a.asdf
"""
Then you can use this package to format it so that it is better readable
from sql_formatter.core import format_sql
print(format_sql(example_sql))
CREATE OR REPLACE TABLE mytable AS -- mytable example
SELECT a.asdf,
b.qwer, -- some comment here
c.asdf, -- some comment there
b.asdf2
FROM table1 as a
LEFT JOIN table2 as b -- and here a comment
ON a.asdf = b.asdf -- join this way
INNER JOIN table3 as c
ON a.asdf = c.asdf
WHERE a.asdf = 1 -- comment this
and b.qwer = 2
and a.asdf <= 1 --comment that
or b.qwer >= 5
GROUP BY a.asdf
It can even deal with subqueries and it will correct my favourite simple careless mistake (comma at the end of SELECT statement before of FROM) for you on the flow :-)
print(format_sql("""
select asdf, cast(qwer as numeric), -- some comment
qwer1
from
(select asdf, qwer, from table1 where asdf = 1) as a
left
join (select asdf, qwer2 from table2 where qwer2 = 1) as b
on a.asdf = b.asdf
where qwer1 >= 0
"""))
SELECT asdf,
cast(qwer as numeric), -- some comment
qwer1
FROM (SELECT asdf,
qwer
FROM table1
WHERE asdf = 1) as a
LEFT JOIN (SELECT asdf,
qwer2
FROM table2
WHERE qwer2 = 1) as b
ON a.asdf = b.asdf
WHERE qwer1 >= 0
The formatter is also robust against nested subqueries
print(format_sql("""
select field1, field2 from (select field1,
field2 from (select field1, field2,
field3 from table1 where a=1 and b>=100))
"""))
SELECT field1,
field2
FROM (SELECT field1,
field2
FROM (SELECT field1,
field2,
field3
FROM table1
WHERE a = 1
and b >= 100))
If you do not want to get some query formatted in your SQL file then you can use the marker /*skip-formatter*/
in your query to disable formatting for just the corresponding query
from sql_formatter.format_file import format_sql_commands
print(format_sql_commands(
"""
use database my_database;
-- My first view --
create or repLace view my_view as
select asdf, qwer from table1
where asdf <= 10;
/*skip-formatter*/
create oR rePlace tabLe my_table as
select asdf
From my_view;
"""
))
use database my_database;
-- My first view --
CREATE OR REPLACE VIEW my_view AS
SELECT asdf,
qwer
FROM table1
WHERE asdf <= 10;
/*skip-formatter*/
create oR rePlace tabLe my_table as
select asdf
From my_view;
For the SQL-formatter to work properly you should meticulously end each of your SQL statements with semicolon (;)
However, we have equiped the sql-formatter
with some basic validations:
CREATE
keyword appears more than twice, indicating the user that he / she may have forgotten a semicoloncase when ... end
: The validator will check if there are case when
statements without end
or vice versasql_formatter
does not doThis package is just a SQL formatter and therefore
Up to now it only formats queries of the form
CREATE TABLE / VIEW ...
SELECT ...
Every other SQL commands will remain unformatted, e.g. INSERT INTO
...
The main goal of the sql_formatter
is to enhance readability and quick understanding of SQL queries via proper formatting. We use indentation and lowercasing / uppercasing as means to arrange statements / clauses and parameters into context. By programmatically standardizing the way to write SQL queries we help the user understand its queries faster.
As a by-product of using the sql_formatter
, developer teams can focus on the query logic itself and save time by not incurring into styling decisions, this then begin accomplished by the sql_formatter
. This is similar to the goal accomplished by the black package for the Python language, which was also an inspiration for the development of this package for SQL.
We can summarize the main steps of the formatter as follows:
* Main statements:
SELECT field1,
case when field2 > 1 and
field2 <= 10 and
field1 = 'a' then 1
else 0 end as case_field,
...
FROM table1
WHERE field1 = 1
and field2 <= 2
or field3 = 5
ORDER BY field1;
This is a very nice, easy example but things can become more complicated if comments come into play
SELECT a.field1,
a.field2,
b.field3
FROM (SELECT field1,
field2
FROM table1
WHERE field1 = 1) as a
LEFT JOIN (SELECT field1,
field3
FROM table2) as b
ON a.field1 = b.field1;
CREATE ... TABLE / VIEW
or SELECT ...
is left unchangedWe version our package via semantic versioning, i.e.,
New documentation, refactoring / maintenance of code and admin tasks do not change the versions.
You can follow the changes introduced by each version in our CHANGELOG
See CONTRIBUTING
Thank you very much to Jeremy Howard and all the nbdev team for enabling the fast and delightful development of this library via the nbdev
framework.
For more details on nbdev
, see its official tutorial
Thank you very much for the developers of the black package, which was also an inspiration for the development of this package
FAQs
A SQL formatter
We found that sql-formatter demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.