Skip to content

Instantly share code, notes, and snippets.

@finsterthecat
Created January 31, 2011 18:42
Show Gist options
  • Save finsterthecat/804548 to your computer and use it in GitHub Desktop.
Save finsterthecat/804548 to your computer and use it in GitHub Desktop.
Drops certain options and qualifiers from create table statements. Could this be any more complicated?
import re, sys, getopt
from collections import deque
DEFAULT_STATEMENT_TERMINATOR = ';'
OPTION_PATTERN = re.compile('''^--<ScriptOptions (.*)/>''', re.I)
TERM_OPTION_PATTERN = re.compile('''^--<ScriptOptions.*statementTerminator="(.*)"/>''', re.I)
TERM_OPTION = '''--<ScriptOptions statementTerminator="%s"/>'''
LOGGING_PATTERN = re.compile('''(.*)^\s+LOGGING\s*$(.*)''', re.I + re.S + re.M)
PCTFREE_PATTERN = re.compile('''(.*)^\s+PCTFREE\s+\d+$(.*)''', re.I + re.S + re.M)
PCTUSED_PATTERN = re.compile('''(.*)^\s+PCTUSED\s+\d+$(.*)''', re.I + re.S + re.M)
STORAGE_PATTERN = re.compile('''(.*)^\s+STORAGE\s*\(.*?\)\s*$(.*)''', re.I + re.S + re.M)
class DDL:
def __init__(self, source, term=DEFAULT_STATEMENT_TERMINATOR):
self.source = source
self.options = []
self.term = term
self.ddlterm = None
self.__ahead = deque()
self.__read_options()
def __read_options(self):
while True:
line = self.source.next()
if line:
if not OPTION_PATTERN.match(line.strip()):
self.__ahead.append(line)
return
else:
line = line.strip()
term = TERM_OPTION_PATTERN.match(line)
if term: self.term = self.ddlterm = term.group(1)
else: self.options.append(line)
def __iter__(self):
return self
def next(self):
stmt = ''
while True:
try:
if self.__ahead: line = self.__ahead.popleft()
else: line = self.source.next()
_line = line.rstrip()
if _line and _line[-1] == self.term:
stmt += _line[0:-1]
return stmt
else: stmt += line
except StopIteration:
if stmt.strip(): return stmt
else: raise StopIteration
def process_ddl(ifile, ofile, patterns, term=DEFAULT_STATEMENT_TERMINATOR, newterm=None):
ddl = DDL(ifile, term)
if ddl.ddlterm:
term = ddl.ddlterm
if not newterm: newterm = term
if ddl.ddlterm: print >> ofile, TERM_OPTION % newterm
for option in ddl.options:
print >> ofile, option
for stmt in ddl:
for pattern in patterns:
match = pattern.match(stmt)
if match: stmt = match.group(1).rstrip() + match.group(2).rstrip()
print >> ofile, '%s%s' % (stmt, newterm)
HELP = '''\
DDL Post-Processing Tool v1.0
Usage: ppddl [OPTIONS] <input DDL file> <output DDL file>
OPTIONS:
--all suppresses all qualifiers
("LOGGING", "PCTFREE", "PCTUSED", "STORAGE")
--logging suppresses "LOGGING" qualifiers
--pctfree suppresses "PCTFREE" qualifiers
--pctused suppresses "PCTUSED" qualifiers
--storage suppresses "STORAGE" qualifiers
--term=TERM specifies statement terminator character.
If terminator is not specified "ScriptOptions" headers
of input DDL script will be used to detect it.
If appropriate "ScriptOptions" header is not present
";" will be used
--new-term=TERM specifies new statement terminator character
to replace existing.
EXAMPLES:
Read "script.ddl" file, auto-detect statement terminator,
suppress all qualifiers, write the result to "new-script.ddl"
ppddl --all script.ddl new-script.ddl
Read "script.ddl" file, use "!" as a statement terminator,
suppress all qualifiers, write the result to "new-script.ddl"
ppddl --all --term="!" script.ddl new-script.ddl
Read "script.ddl" file, auto-detect statement terminator,
suppress "STORAGE" and "LOGGING" qualifiers,
write the result to "new-script.ddl"
using ";" as a statement terminator
ppddl --storage --logging --new-term=";" script.ddl new-script.ddl
'''
def report_help():
print HELP
sys.exit(0)
USAGE = '''\
DDL Post-Processing Tool v1.0
Usage: ppddl [OPTIONS] <input DDL file> <output DDL file>
Try "ppddl --help" for more options.
'''
def report_usage_error(error):
print error
print USAGE
sys.exit(2)
def init(options):
try:
opts, args = getopt.getopt(options, '', ['help', 'all', 'logging', 'pctfree', 'pctused', 'storage', 'term=', 'new-term='])
except getopt.GetoptError, err:
report_usage_error(str(err))
patterns = []
term = DEFAULT_STATEMENT_TERMINATOR
newterm = None
for opt, value in opts:
if opt == "--help": report_help()
elif opt == '--all': patterns.extend([LOGGING_PATTERN, PCTFREE_PATTERN, PCTUSED_PATTERN, STORAGE_PATTERN])
elif opt == '--logging': patterns.append(LOGGING_PATTERN)
elif opt == '--pctfree': patterns.append(PCTFREE_PATTERN)
elif opt == '--pctused': patterns.append(PCTUSED_PATTERN)
elif opt == '--storage': patterns.append(STORAGE_PATTERN)
elif opt == '--term': term = value
elif opt == '--new-term': newterm = value
else:
report_usage_error("Unknown option : '%s'" % opt)
if len(args) != 2:
report_usage_error("Two arguments are required: input DDL and output DDL files")
if not patterns:
patterns.extend([LOGGING_PATTERN, PCTFREE_PATTERN, PCTUSED_PATTERN, STORAGE_PATTERN])
return args[0], args[1], patterns, term, newterm
if __name__ == '__main__':
ifile, ofile, patterns, term, newterm = init(sys.argv[1:])
ifile, ofile = open(ifile, 'r'), open(ofile, 'w')
try:
process_ddl(ifile, ofile, patterns, term, newterm)
finally:
ifile.close()
ofile.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment