]> git.phdru.name Git - sqlconvert.git/blob - scripts/mysql2sql
Fix mysql2sql: do not mix output and messages
[sqlconvert.git] / scripts / mysql2sql
1 #! /usr/bin/env python
2 from __future__ import print_function
3
4 import argparse
5 from io import open
6 import os
7 import sys
8
9 from sqlparse.compat import text_type
10 from sqlconvert.print_tokens import print_tokens
11 from sqlconvert.process_mysql import is_directive_statement, process_statement
12 from sqlconvert.process_tokens import is_newline_statement, StatementGrouper
13
14 from m_lib.defenc import default_encoding
15 from m_lib.pbar.tty_pbar import ttyProgressBar
16
17
18 def get_fsize(fp):
19     try:
20         fp.seek(0, os.SEEK_END)
21     except IOError:
22         return None  # File size is unknown
23     size = fp.tell()
24     fp.seek(0, os.SEEK_SET)
25     return size
26
27
28 def main(infile, encoding, outfile, output_encoding, use_pbar, quoting_style):
29     if use_pbar:
30         size = get_fsize(infile)
31         if size is None:
32             use_pbar = False
33
34     if use_pbar:
35         print("Converting: ", end='', file=sys.stderr)
36     sys.stderr.flush()
37
38     if use_pbar:
39         pbar = ttyProgressBar(0, size-1)
40         cur_pos = 0
41
42     grouper = StatementGrouper(encoding=encoding)
43     got_directive = False
44     for line in infile:
45         if use_pbar:
46             if isinstance(line, text_type):
47                 cur_pos += len(line.encode(encoding))
48             else:
49                 cur_pos += len(line)
50             pbar.display(cur_pos)
51         grouper.process_line(line)
52         for statement in grouper.get_statements():
53             if got_directive and is_newline_statement(statement):
54                 # Condense a sequence of newlines after a /*! directive */;
55                 got_directive = False
56                 continue
57             got_directive = is_directive_statement(statement)
58             if got_directive:
59                 continue
60             for statement in process_statement(statement, quoting_style):
61                 print_tokens(statement, outfile=outfile,
62                              encoding=output_encoding)
63     tokens = grouper.close()
64     if tokens:
65         for token in tokens:
66             print_tokens(token, outfile=outfile, encoding=output_encoding)
67
68     if use_pbar:
69         pbar.erase()
70         print("done.")
71
72 if __name__ == '__main__':
73     parser = argparse.ArgumentParser(description='Convert MySQL to SQL')
74     parser.add_argument('-e', '--encoding', default='utf-8',
75                         help='input/output encoding, default is utf-8')
76     parser.add_argument('-E', '--output-encoding',
77                         help='separate output encoding, default is the same '
78                         'as -e except for console; for console output '
79                         'charset from the current locale is used')
80     parser.add_argument('-m', '--mysql', action='store_true',
81                         help='MySQL/MariaDB quoting style')
82     parser.add_argument('-p', '--pg', '--postgres', action='store_true',
83                         help='PostgreSQL quoting style')
84     parser.add_argument('-s', '--sqlite', action='store_true',
85                         help='Generic SQL/SQLite quoting style; '
86                         'this is the default')
87     parser.add_argument('-o', '--outfile', help='output file name')
88     parser.add_argument('-P', '--no-pbar', action='store_true',
89                         help='inhibit progress bar')
90     parser.add_argument('infile', help='input file name')
91     parser.add_argument('output_file', nargs='?', help='output file name')
92     args = parser.parse_args()
93
94     if int(args.mysql) + int(args.pg) + int(args.sqlite) > 1:
95         print("Error: options -m/-p/-s are mutually incompatible, "
96               "use only one of them",
97               file=sys.stderr)
98         parser.print_help()
99         sys.exit(1)
100
101     if args.infile:
102         if args.infile == '-':
103             infile = sys.stdin
104         else:
105             infile = open(args.infile, 'rt', encoding=args.encoding)
106     else:
107         infile = sys.stdin
108
109     if infile.isatty():
110         print("Error: cannot read from console", file=sys.stderr)
111         parser.print_help()
112         sys.exit(1)
113
114     if args.outfile:
115         if args.output_file:
116             print("Error: too many output files", file=sys.stderr)
117             parser.print_help()
118             sys.exit(1)
119
120         outfile = args.outfile
121
122     elif args.output_file:
123         outfile = args.output_file
124
125     else:
126         outfile = '-'
127
128     if args.output_encoding:
129         output_encoding = args.output_encoding
130     elif outfile == '-':
131         output_encoding = default_encoding
132     else:
133         output_encoding = args.encoding
134
135     if outfile == '-':
136         outfile = sys.stdout
137         args.no_pbar = True
138     else:
139         try:
140             outfile = open(outfile, 'wt', encoding=output_encoding)
141         except:
142             if infile is not sys.stdin:
143                 infile.close()
144             raise
145
146     if args.mysql:
147         quoting_style = 'mysql'
148     elif args.pg:
149         quoting_style = 'postgres'
150     else:
151         quoting_style = 'sqlite'
152
153     main(infile, args.encoding, outfile, output_encoding, not args.no_pbar,
154          quoting_style)