Giter Site home page Giter Site logo

benjie / prettier-plugin-pg Goto Github PK

View Code? Open in Web Editor NEW
278.0 23.0 5.0 433 KB

[WIP] Plugin for prettier to support formatting of PostgreSQL-flavour SQL, including function bodies in SQL, pgSQL, PLV8, plpython, etc.

License: MIT License

JavaScript 9.20% PLpgSQL 0.40% TypeScript 90.40%

prettier-plugin-pg's Introduction

prettier-plugin-pg

Package on npm MIT license Gitter chat room Patreon donate button Donate Follow

This is a work-in-progress plugin for prettier to support formatting of PostgreSQL-flavour SQL, including formatting view and function bodies as SQL, PL/pgSQL, Python (plpython), JavaScript (plv8) etc.

Guiding principles

Try and match pg_dump-style capitalisation and word order, but with prettier line-wrapping/indentation.

  • Capitalise keywords
  • Use lower case for case-insensitive identifiers (table/column/function/etc names)
  • Only escape case-insensitive identifiers if they are reserved words
  • Always escape identifiers if they are reserved words
  • Always escape case-sensitive identifiers (obviously)
  • Where a statement can be expressed in many orders, express it in the same order that pg_dump would
  • Try not to add/remove things (e.g. functions are volatile by default, mark them as VOLATILE in the output if and only if they were marked as such in the input (otherwise omit))
  • Be safe! If we don't understand something, throw an error - don't just carry on regardless!

How to use it

Don't! We're not ready yet!

git clone [email protected]:benjie/prettier-plugin-pg.git
cd prettier-plugin-pg
yarn

Then compile the source (watch flag is optional):

yarn tsc --watch

And in another terminal:

yarn test

How it works / history

We use pg-query-native which uses libpq_query to parse the SQL using the same parser code that PostgreSQL uses internally.

We then took the deparser from pg-query-parser as the foundation for the printer, and converted it from using strings internally to using prettier's formatting commands. [This is where we're working currently.]

We've not got this far yet, but next we'll be adding a library of tests (if you have any particularly tricky SQL, please submit it!) to ensure that nothing is corrupted.

Finally we'll be optimising the formatting of the output queries - putting the groups and lines in the correct places.

Status

Very much a work in progress - do NOT use this for basically ANYTHING yet, we've got a long way to go.

Contributing

Help would be very much appreciated - just jot down in an issue what you'd like to do and if you get the nod (which tends to be fairly prompt!) then please send a PR. Issues will be opened up to other contributors after a short period of inactivity, so you're encouraged to open a PR before it's ready to merge, just mark it as [WIP] in the PR title.

Self-promotion

While I've got your attention:

  • my open source work is self-funded through freelance consulting work and generous donations from the community, you can support my open source work via Patreon, or PayPal
  • you can follow me on Twitter: @benjie
  • if you're looking for an instant GraphQL server for your PostgreSQL database that leverages the power of PostgreSQL and doesn't fall foul of N+1 issues, check out PostGraphile (formerly PostGraphQL)

prettier-plugin-pg's People

Contributors

benjie avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prettier-plugin-pg's Issues

Failed to build and run the tests

I wanted to try out this plugin, but failed to build it locally on MacOS Monterey.

First off I was missing Python. Then it probably wasn't happy with the version of Python:

gyp ERR! configure error 
gyp ERR! stack Error: Command failed: /usr/bin/python3 -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                       ^
gyp ERR! stack SyntaxError: invalid syntax

Looks like the problem stems from pg-query-native-latest which uses node-gyp 3.8.0.

The docs for node-gyp say that there are problems with running it on MacOS Catalina or later and the advised solution is to upgrade to node-gyp >= 7.

I tried swapping pg-query-native-latest 1.1.1 with pg-query-native 1.3.1 which uses node-gyp 8.2 (also renaming typings/pg-query-native-latest.d.ts to typings/pg-query-native.d.ts and changing references to pg-query-native-latest elsewhere). This did fix the installation. I was also able to compile the code with tsc. But the tests failed to run, with error messages like:

 FAIL   test  tests/BEGIN/jsfmt.spec.js
  โ— Test suite failed to run

    Node doesn't have location:

    {
      TransactionStmt: {
        kind: 0,
        options: [
          {
            DefElem: {
              defname: 'transaction_deferrable',
              arg: { A_Const: [Object] },
              defaction: 0
            }
          }
        ]
      }
    }

    Parent node:

    {
      Document: {
        statements: [
          { TransactionStmt: { kind: 0, options: [Array] } },
          { TransactionStmt: { kind: 0, options: [Array] } }
        ],
        doc_location: 0,
        doc_len: 50
      },
      comments: [ { LineComment: true, value: '-- Hello!', start: 0, end: 9 } ],
      start: 0,
      end: 50
    }

Implement more SQL statements

I've added a selection of the statements I see as the most commonly used in a list here. To create the test folder for a statement, run:

npm run add-statement "CREATE FUNCTION"

then create an SQL file such as tests/CREATE_FUNCTION/basic.sql and add some SQL to it.

  • SELECT
  • INSERT
  • UPDATE
  • DELETE
  • TRUNCATE

  • CREATE TABLE
  • ALTER TABLE
  • DROP TABLE

  • CREATE INDEX
  • ALTER INDEX
  • DROP INDEX

  • BEGIN
  • SET
  • COMMIT
  • ROLLBACK

  • CREATE SCHEMA
  • DROP SCHEMA

  • CREATE EXTENSION
  • DROP EXTENSION

  • GRANT
  • REVOKE
  • ALTER DEFAULT PRIVILEGES
  • CREATE POLICY
  • DROP POLICY

  • CREATE FUNCTION
  • ALTER FUNCTION
  • DROP FUNCTION
  • DO

  • CREATE TRIGGER
  • DROP TRIGGER

  • CREATE VIEW
  • ALTER VIEW
  • DROP VIEW
  • CREATE MATERIALIZED VIEW
  • ALTER MATERIALIZED VIEW
  • REFRESH MATERIALIZED VIEW
  • DROP MATERIALIZED VIEW

  • COMMENT ON COLUMN
  • COMMENT ON FUNCTION
  • COMMENT ON TABLE

  • CREATE TYPE
  • DROP TYPE

  • CREATE DOMAIN
  • ALTER DOMAIN
  • DROP DOMAIN

  • LISTEN
  • UNLISTEN
  • NOTIFY

  • VACUUM

Humbly Checking for Status Updates

First off, thanks for all the incredible things you do for the open source commuinity @benjie. You're definitely an inspiration on multiple levels. Hopefully this issue doesn't come as a nuisance so please feel free to close if this just isn't on your radar right now.

I went down a crazy rabbit hole today trying to find some kind of tool I could use inside of our repo to apply consistent formatting to Postgres SQL migrations and a bunch of more complex Postgres Functions that we manage. I'm spoiled into assuming that in the Node ecosystem these types of tools are readily accessible but there doesn't seem to be many good options out there. This project definitely seems the most promising both because of it's integration with Prettier and the architectural approach you're taking.

Was just wondering if you plan to revisit and continue work on this or if it's on the backburner because of your other more high profile projects (totally understandable)? Anyways, thanks again and I just wanted to give a huge thumbs up that if this ever got released it would be something that would definitely help out both the org I work for and me personally!

Add support for comments

It seems that the native PostgreSQL query parser simply treats comments as whitespace (and drops them). See: pganalyze/libpg_query#15

To support comments we're either going to have to do something ugly with regexps (ick), write our own AST parser (ugh), or dive into the C-code of libpg_query, maybe starting around here: https://github.com/lfittl/libpg_query/blob/cd9e4b33cef948461c0354a81a23082b16c6a8d1/src/postgres/src_backend_parser_parser.c#L43-L70

This is a major issue. Without comments, we shouldn't really consider progressing.

Alternative formatters before this is ready

While we're waiting for prettier-plugin-pg to be ready (see #10) here are some alternatives that you may have success with already today:

  1. prettier-plugin-embed and prettier-plugin-sql by @JounQin and @Sec-ant - uses sql-formatter by @nene
  2. eslint-plugin-sql and eslint-plugin-unicorn by @gajus, @sindresorhus, @fregante, @mmkal, @fisker and @npdev45, but very opinionated / not so configurable - uses pg-formatter by @gajus
  3. @potygen/prettier-plugin-pgsql by @ivank - uses custom Prettier AST formatter

Finish converting `print.js` to use the prettier helpers

print.js was originally based on this file to give us a head start:

https://github.com/pyramation/pg-query-parser/blob/8a83b18bfd3ff85d40f10ea1d679e4605a8b1022/src/deparser.js

It's been reformatted to not be class-based, but the code still needs quite a bit of re-writing. When you're confused what the code is doing it's probably because it's broken - look at the relevant part of the old code to see what the intent was.

Everywhere that's currently using deparse needs to go - we've changed the signature of the visitors so they need to be used with print now instead.

Old code was like this:

['A_Indices'](node) {
  // ...
}

New code generally follows this pattern:

['A_Indices'](path, options, print) {
  const node = path.getValue(); // < This is the same node as in the old code
  // ...
}

Here's come common patterns in the ... section above:

Old code:

    if (node.lidx) {
      return format('[%s:%s]', this.deparse(node.lidx), this.deparse(node.uidx));
    }

    return format('[%s]', this.deparse(node.uidx));

New code:

    if (node.lidx) {
      return concat(['[', path.call(print, 'lidx'), ':', path.call(print, 'uidx'), ']']);
    }

    return concat(['[', path.call(print, 'uidx'), ']']);

Old code:

    const fields = node.fields.map(field => {
      return this.deparse(field);
    });

    return fields.join('.');

New code:

    return join('.', path.map(print, 'fields'));

Note the helpers:

  • path.call(callback, path1, path2, ...) - will call callback passing a new FastPath object that represents node[path1][path2] - note that the path elements can be strings (for objects) or numbers (for arrays).
  • path.map(callback, path1, path2, ...) - as path.call except the entry identified by node[path1][path2] is expected to be an array, so the callback is called for each entry of that array.

Since prettier is happy dealing with strings it's wise to start at the bottom (i.e. the "statement" AST nodes) and then work your way up through the tree until all branches and leaves are prettier Doc elements.

Handy reference:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.