codekingpro/portable-devtools
115k
1#2# Copyright (C) 2009-2020 the sqlparse authors and contributors3# <see AUTHORS file>4#5# This module is part of python-sqlparse and is released under6# the BSD License: https://opensource.org/licenses/BSD-3-Clause7 8"""SQL formatter"""9 10from sqlparse import filters11from sqlparse.exceptions import SQLParseError12 13 14def validate_options(options):15 """Validates options."""16 kwcase = options.get('keyword_case')17 if kwcase not in [None, 'upper', 'lower', 'capitalize']:18 raise SQLParseError('Invalid value for keyword_case: '19 '{!r}'.format(kwcase))20 21 idcase = options.get('identifier_case')22 if idcase not in [None, 'upper', 'lower', 'capitalize']:23 raise SQLParseError('Invalid value for identifier_case: '24 '{!r}'.format(idcase))25 26 ofrmt = options.get('output_format')27 if ofrmt not in [None, 'sql', 'python', 'php']:28 raise SQLParseError('Unknown output format: '29 '{!r}'.format(ofrmt))30 31 strip_comments = options.get('strip_comments', False)32 if strip_comments not in [True, False]:33 raise SQLParseError('Invalid value for strip_comments: '34 '{!r}'.format(strip_comments))35 36 space_around_operators = options.get('use_space_around_operators', False)37 if space_around_operators not in [True, False]:38 raise SQLParseError('Invalid value for use_space_around_operators: '39 '{!r}'.format(space_around_operators))40 41 strip_ws = options.get('strip_whitespace', False)42 if strip_ws not in [True, False]:43 raise SQLParseError('Invalid value for strip_whitespace: '44 '{!r}'.format(strip_ws))45 46 truncate_strings = options.get('truncate_strings')47 if truncate_strings is not None:48 try:49 truncate_strings = int(truncate_strings)50 except (ValueError, TypeError):51 raise SQLParseError('Invalid value for truncate_strings: '52 '{!r}'.format(truncate_strings))53 if truncate_strings <= 1:54 raise SQLParseError('Invalid value for truncate_strings: '55 '{!r}'.format(truncate_strings))56 options['truncate_strings'] = truncate_strings57 options['truncate_char'] = options.get('truncate_char', '[...]')58 59 indent_columns = options.get('indent_columns', False)60 if indent_columns not in [True, False]:61 raise SQLParseError('Invalid value for indent_columns: '62 '{!r}'.format(indent_columns))63 elif indent_columns:64 options['reindent'] = True # enforce reindent65 options['indent_columns'] = indent_columns66 67 reindent = options.get('reindent', False)68 if reindent not in [True, False]:69 raise SQLParseError('Invalid value for reindent: '70 '{!r}'.format(reindent))71 elif reindent:72 options['strip_whitespace'] = True73 74 reindent_aligned = options.get('reindent_aligned', False)75 if reindent_aligned not in [True, False]:76 raise SQLParseError('Invalid value for reindent_aligned: '77 '{!r}'.format(reindent))78 elif reindent_aligned:79 options['strip_whitespace'] = True80 81 indent_after_first = options.get('indent_after_first', False)82 if indent_after_first not in [True, False]:83 raise SQLParseError('Invalid value for indent_after_first: '84 '{!r}'.format(indent_after_first))85 options['indent_after_first'] = indent_after_first86 87 indent_tabs = options.get('indent_tabs', False)88 if indent_tabs not in [True, False]:89 raise SQLParseError('Invalid value for indent_tabs: '90 '{!r}'.format(indent_tabs))91 elif indent_tabs:92 options['indent_char'] = '\t'93 else:94 options['indent_char'] = ' '95 96 indent_width = options.get('indent_width', 2)97 try:98 indent_width = int(indent_width)99 except (TypeError, ValueError):100 raise SQLParseError('indent_width requires an integer')101 if indent_width < 1:102 raise SQLParseError('indent_width requires a positive integer')103 options['indent_width'] = indent_width104 105 wrap_after = options.get('wrap_after', 0)106 try:107 wrap_after = int(wrap_after)108 except (TypeError, ValueError):109 raise SQLParseError('wrap_after requires an integer')110 if wrap_after < 0:111 raise SQLParseError('wrap_after requires a positive integer')112 options['wrap_after'] = wrap_after113 114 comma_first = options.get('comma_first', False)115 if comma_first not in [True, False]:116 raise SQLParseError('comma_first requires a boolean value')117 options['comma_first'] = comma_first118 119 right_margin = options.get('right_margin')120 if right_margin is not None:121 try:122 right_margin = int(right_margin)123 except (TypeError, ValueError):124 raise SQLParseError('right_margin requires an integer')125 if right_margin < 10:126 raise SQLParseError('right_margin requires an integer > 10')127 options['right_margin'] = right_margin128 129 return options130 131 132def build_filter_stack(stack, options):133 """Setup and return a filter stack.134 135 Args:136 stack: :class:`~sqlparse.filters.FilterStack` instance137 options: Dictionary with options validated by validate_options.138 """139 # Token filter140 if options.get('keyword_case'):141 stack.preprocess.append(142 filters.KeywordCaseFilter(options['keyword_case']))143 144 if options.get('identifier_case'):145 stack.preprocess.append(146 filters.IdentifierCaseFilter(options['identifier_case']))147 148 if options.get('truncate_strings'):149 stack.preprocess.append(filters.TruncateStringFilter(150 width=options['truncate_strings'], char=options['truncate_char']))151 152 if options.get('use_space_around_operators', False):153 stack.enable_grouping()154 stack.stmtprocess.append(filters.SpacesAroundOperatorsFilter())155 156 # After grouping157 if options.get('strip_comments'):158 stack.enable_grouping()159 stack.stmtprocess.append(filters.StripCommentsFilter())160 161 if options.get('strip_whitespace') or options.get('reindent'):162 stack.enable_grouping()163 stack.stmtprocess.append(filters.StripWhitespaceFilter())164 165 if options.get('reindent'):166 stack.enable_grouping()167 stack.stmtprocess.append(168 filters.ReindentFilter(169 char=options['indent_char'],170 width=options['indent_width'],171 indent_after_first=options['indent_after_first'],172 indent_columns=options['indent_columns'],173 wrap_after=options['wrap_after'],174 comma_first=options['comma_first']))175 176 if options.get('reindent_aligned', False):177 stack.enable_grouping()178 stack.stmtprocess.append(179 filters.AlignedIndentFilter(char=options['indent_char']))180 181 if options.get('right_margin'):182 stack.enable_grouping()183 stack.stmtprocess.append(184 filters.RightMarginFilter(width=options['right_margin']))185 186 # Serializer187 if options.get('output_format'):188 frmt = options['output_format']189 if frmt.lower() == 'php':190 fltr = filters.OutputPHPFilter()191 elif frmt.lower() == 'python':192 fltr = filters.OutputPythonFilter()193 else:194 fltr = None195 if fltr is not None:196 stack.postprocess.append(fltr)197 198 return stack199 