mirror of
https://github.com/apache/impala.git
synced 2025-12-19 18:12:08 -05:00
Upgrades the impala-shell's bundled version of sqlparse to 0.3.1. There were some API changes in 0.2.0+ that required a re-write of the StripLeadingCommentFilter in impala_shell.py. A slight perf optimization was also added to avoid using the filter altogether if no leading comment is readily discernible. As 0.1.19 was the last version of sqlparse to support python 2.6, this patch also breaks Impala's compatibility with python 2.6. No new tests were added, but all existing tests passed without modification. Change-Id: I77a1fd5ae311634a18ee04b8c389d8a3f3a6e001 Reviewed-on: http://gerrit.cloudera.org:8080/15642 Reviewed-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
203 lines
5.8 KiB
Python
Executable File
203 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2009-2018 the sqlparse authors and contributors
|
|
# <see AUTHORS file>
|
|
#
|
|
# This module is part of python-sqlparse and is released under
|
|
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
|
|
|
|
"""Module that contains the command line app.
|
|
|
|
Why does this file exist, and why not put this in __main__?
|
|
You might be tempted to import things from __main__ later, but that will
|
|
cause problems: the code will get executed twice:
|
|
- When you run `python -m sqlparse` python will execute
|
|
``__main__.py`` as a script. That means there won't be any
|
|
``sqlparse.__main__`` in ``sys.modules``.
|
|
- When you import __main__ it will get executed again (as a module) because
|
|
there's no ``sqlparse.__main__`` in ``sys.modules``.
|
|
Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
from io import TextIOWrapper
|
|
from codecs import open, getreader
|
|
|
|
import sqlparse
|
|
from sqlparse.compat import PY2
|
|
from sqlparse.exceptions import SQLParseError
|
|
|
|
|
|
# TODO: Add CLI Tests
|
|
# TODO: Simplify formatter by using argparse `type` arguments
|
|
def create_parser():
|
|
_CASE_CHOICES = ['upper', 'lower', 'capitalize']
|
|
|
|
parser = argparse.ArgumentParser(
|
|
prog='sqlformat',
|
|
description='Format FILE according to OPTIONS. Use "-" as FILE '
|
|
'to read from stdin.',
|
|
usage='%(prog)s [OPTIONS] FILE, ...',
|
|
)
|
|
|
|
parser.add_argument('filename')
|
|
|
|
parser.add_argument(
|
|
'-o', '--outfile',
|
|
dest='outfile',
|
|
metavar='FILE',
|
|
help='write output to FILE (defaults to stdout)')
|
|
|
|
parser.add_argument(
|
|
'--version',
|
|
action='version',
|
|
version=sqlparse.__version__)
|
|
|
|
group = parser.add_argument_group('Formatting Options')
|
|
|
|
group.add_argument(
|
|
'-k', '--keywords',
|
|
metavar='CHOICE',
|
|
dest='keyword_case',
|
|
choices=_CASE_CHOICES,
|
|
help='change case of keywords, CHOICE is one of {0}'.format(
|
|
', '.join('"{0}"'.format(x) for x in _CASE_CHOICES)))
|
|
|
|
group.add_argument(
|
|
'-i', '--identifiers',
|
|
metavar='CHOICE',
|
|
dest='identifier_case',
|
|
choices=_CASE_CHOICES,
|
|
help='change case of identifiers, CHOICE is one of {0}'.format(
|
|
', '.join('"{0}"'.format(x) for x in _CASE_CHOICES)))
|
|
|
|
group.add_argument(
|
|
'-l', '--language',
|
|
metavar='LANG',
|
|
dest='output_format',
|
|
choices=['python', 'php'],
|
|
help='output a snippet in programming language LANG, '
|
|
'choices are "python", "php"')
|
|
|
|
group.add_argument(
|
|
'--strip-comments',
|
|
dest='strip_comments',
|
|
action='store_true',
|
|
default=False,
|
|
help='remove comments')
|
|
|
|
group.add_argument(
|
|
'-r', '--reindent',
|
|
dest='reindent',
|
|
action='store_true',
|
|
default=False,
|
|
help='reindent statements')
|
|
|
|
group.add_argument(
|
|
'--indent_width',
|
|
dest='indent_width',
|
|
default=2,
|
|
type=int,
|
|
help='indentation width (defaults to 2 spaces)')
|
|
|
|
group.add_argument(
|
|
'--indent_after_first',
|
|
dest='indent_after_first',
|
|
action='store_true',
|
|
default=False,
|
|
help='indent after first line of statement (e.g. SELECT)')
|
|
|
|
group.add_argument(
|
|
'--indent_columns',
|
|
dest='indent_columns',
|
|
action='store_true',
|
|
default=False,
|
|
help='indent all columns by indent_width instead of keyword length')
|
|
|
|
group.add_argument(
|
|
'-a', '--reindent_aligned',
|
|
action='store_true',
|
|
default=False,
|
|
help='reindent statements to aligned format')
|
|
|
|
group.add_argument(
|
|
'-s', '--use_space_around_operators',
|
|
action='store_true',
|
|
default=False,
|
|
help='place spaces around mathematical operators')
|
|
|
|
group.add_argument(
|
|
'--wrap_after',
|
|
dest='wrap_after',
|
|
default=0,
|
|
type=int,
|
|
help='Column after which lists should be wrapped')
|
|
|
|
group.add_argument(
|
|
'--comma_first',
|
|
dest='comma_first',
|
|
default=False,
|
|
type=bool,
|
|
help='Insert linebreak before comma (default False)')
|
|
|
|
group.add_argument(
|
|
'--encoding',
|
|
dest='encoding',
|
|
default='utf-8',
|
|
help='Specify the input encoding (default utf-8)')
|
|
|
|
return parser
|
|
|
|
|
|
def _error(msg):
|
|
"""Print msg and optionally exit with return code exit_."""
|
|
sys.stderr.write(u'[ERROR] {0}\n'.format(msg))
|
|
return 1
|
|
|
|
|
|
def main(args=None):
|
|
parser = create_parser()
|
|
args = parser.parse_args(args)
|
|
|
|
if args.filename == '-': # read from stdin
|
|
if PY2:
|
|
data = getreader(args.encoding)(sys.stdin).read()
|
|
else:
|
|
wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding)
|
|
try:
|
|
data = wrapper.read()
|
|
finally:
|
|
wrapper.detach()
|
|
else:
|
|
try:
|
|
with open(args.filename, 'r', args.encoding) as f:
|
|
data = ''.join(f.readlines())
|
|
except IOError as e:
|
|
return _error(
|
|
u'Failed to read {0}: {1}'.format(args.filename, e))
|
|
|
|
close_stream = False
|
|
if args.outfile:
|
|
try:
|
|
stream = open(args.outfile, 'w', args.encoding)
|
|
close_stream = True
|
|
except IOError as e:
|
|
return _error(u'Failed to open {0}: {1}'.format(args.outfile, e))
|
|
else:
|
|
stream = sys.stdout
|
|
|
|
formatter_opts = vars(args)
|
|
try:
|
|
formatter_opts = sqlparse.formatter.validate_options(formatter_opts)
|
|
except SQLParseError as e:
|
|
return _error(u'Invalid options: {0}'.format(e))
|
|
|
|
s = sqlparse.format(data, **formatter_opts)
|
|
stream.write(s)
|
|
stream.flush()
|
|
if close_stream:
|
|
stream.close()
|
|
return 0
|