| 6 | |
| 7 | |
| 8 | class SQL2CSV(CSVKitUtility): |
| 9 | description = 'Execute a SQL query on a database and output the result to a CSV file.' |
| 10 | # Overrides all flags except --linenumbers, --verbose, --version. |
| 11 | override_flags = ['f', 'b', 'd', 'e', 'H', 'I', 'K', 'L', 'p', 'q', 'S', 't', 'u', 'z', 'zero', 'add-bom'] |
| 12 | |
| 13 | def add_arguments(self): |
| 14 | self.argparser.add_argument( |
| 15 | '--db', dest='connection_string', default='sqlite://', |
| 16 | help='A SQLAlchemy connection string to connect to a database.') |
| 17 | self.argparser.add_argument( |
| 18 | '--engine-option', dest='engine_option', nargs=2, action='append', default=[], |
| 19 | help="A keyword argument to SQLAlchemy's create_engine(), as a space-separated pair. " |
| 20 | "This option can be specified multiple times. For example: thick_mode True") |
| 21 | self.argparser.add_argument( |
| 22 | '--execution-option', dest='execution_option', nargs=2, action='append', |
| 23 | # https://docs.sqlalchemy.org/en/20/core/connections.html#sqlalchemy.engine.Connection.execution_options.params.no_parameters |
| 24 | # https://docs.sqlalchemy.org/en/20/core/connections.html#sqlalchemy.engine.Connection.execution_options.params.stream_results |
| 25 | # https://docs.sqlalchemy.org/en/20/core/connections.html#using-server-side-cursors-a-k-a-stream-results |
| 26 | default=[['no_parameters', True], ['stream_results', True]], |
| 27 | help="A keyword argument to SQLAlchemy's execution_options(), as a space-separated pair. " |
| 28 | "This option can be specified multiple times. For example: stream_results True") |
| 29 | self.argparser.add_argument( |
| 30 | metavar='FILE', nargs='?', dest='input_path', |
| 31 | help='The file to use as SQL query. If FILE and --query are omitted, the query is piped data via STDIN.') |
| 32 | self.argparser.add_argument( |
| 33 | '--query', |
| 34 | help="The SQL query to execute. Overrides FILE and STDIN.") |
| 35 | self.argparser.add_argument( |
| 36 | '-e', '--encoding', dest='encoding', default='utf-8', |
| 37 | help='Specify the encoding of the input query file.') |
| 38 | self.argparser.add_argument( |
| 39 | '-H', '--no-header-row', dest='no_header_row', action='store_true', |
| 40 | help='Do not output column names.') |
| 41 | |
| 42 | self.argparser.set_defaults( |
| 43 | delimiter=None, |
| 44 | doublequote=None, |
| 45 | escapechar=None, |
| 46 | encoding='utf-8', |
| 47 | field_size_limit=None, |
| 48 | quotechar=None, |
| 49 | quoting=None, |
| 50 | skipinitialspace=None, |
| 51 | tabs=None, |
| 52 | ) |
| 53 | |
| 54 | def main(self): |
| 55 | if self.additional_input_expected() and not self.args.query: |
| 56 | self.argparser.error('You must provide an input file or piped data.') |
| 57 | |
| 58 | try: |
| 59 | engine = create_engine(self.args.connection_string, **parse_list(self.args.engine_option)) |
| 60 | except ImportError as e: |
| 61 | raise ImportError( |
| 62 | "You don't appear to have the necessary database backend installed for connection string you're " |
| 63 | "trying to use. Available backends include:\n\nPostgreSQL:\tpip install psycopg2\nMySQL:\t\tpip " |
| 64 | "install mysql-connector-python OR pip install mysqlclient\n\nFor details on connection strings " |
| 65 | "and other backends, please see the SQLAlchemy documentation on dialects at:\n\n" |
no outgoing calls