summaryrefslogtreecommitdiff
path: root/scripts/catsql.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/catsql.py')
-rwxr-xr-xscripts/catsql.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/scripts/catsql.py b/scripts/catsql.py
new file mode 100755
index 00000000..94fbacd8
--- /dev/null
+++ b/scripts/catsql.py
@@ -0,0 +1,141 @@
+#! /usr/bin/env python
+
+"""Prints out SQL files with psql command execution.
+
+Supported psql commands: \i, \cd, \q
+Others are skipped.
+
+Aditionally does some pre-processing for NDoc.
+NDoc is looks nice but needs some hand-holding.
+
+Bug:
+
+- function def end detection searches for 'as'/'is' but does not check
+ word boundaries - finds them even in function name. That means in
+ main conf, as/is must be disabled and $ ' added. This script can
+ remove the unnecessary AS from output.
+
+Niceties:
+
+- Ndoc includes function def in output only if def is after comment.
+ But for SQL functions its better to have it after def.
+ This script can swap comment and def.
+
+- Optionally remove CREATE FUNCTION (OR REPLACE) from def to
+ keep it shorter in doc.
+
+Note:
+
+- NDoc compares real function name and name in comment. if differ,
+ it decides detection failed.
+
+"""
+
+import sys, os, re, getopt
+
+def usage(x):
+ print "usage: catsql [--ndoc] FILE [FILE ...]"
+ sys.exit(x)
+
+# NDoc specific changes
+cf_ndoc = 0
+
+# compile regexes
+func_re = r"create\s+(or\s+replace\s+)?function\s+"
+func_rc = re.compile(func_re, re.I)
+comm_rc = re.compile(r"^\s*([#]\s*)?(?P<com>--.*)", re.I)
+end_rc = re.compile(r"\b([;]|begin|declare|end)\b", re.I)
+as_rc = re.compile(r"\s+as\s+", re.I)
+cmd_rc = re.compile(r"^\\([a-z]*)(\s+.*)?", re.I)
+
+# conversion func
+def fix_func(ln):
+ # if ndoc, replace AS with ' '
+ if cf_ndoc:
+ return as_rc.sub(' ', ln)
+ else:
+ return ln
+
+# got function def
+def proc_func(f, ln):
+ # remove CREATE OR REPLACE
+ if cf_ndoc:
+ ln = func_rc.sub('', ln)
+
+ ln = fix_func(ln)
+ pre_list = [ln]
+ comm_list = []
+ n_comm = 0
+ while 1:
+ ln = f.readline()
+ if not ln:
+ break
+
+ com = None
+ if cf_ndoc:
+ com = comm_rc.search(ln)
+ if cf_ndoc and com:
+ pos = com.start('com')
+ comm_list.append(ln[pos:])
+ elif end_rc.search(ln):
+ break
+ elif len(comm_list) > 0:
+ break
+ else:
+ pre_list.append(fix_func(ln))
+
+ if len(comm_list) > 2:
+ map(sys.stdout.write, comm_list)
+ map(sys.stdout.write, pre_list)
+ else:
+ map(sys.stdout.write, pre_list)
+ map(sys.stdout.write, comm_list)
+ if ln:
+ sys.stdout.write(fix_func(ln))
+
+def cat_file(fn):
+ sys.stdout.write("\n")
+ f = open(fn)
+ while 1:
+ ln = f.readline()
+ if not ln:
+ break
+ m = cmd_rc.search(ln)
+ if m:
+ cmd = m.group(1)
+ if cmd == "i": # include a file
+ fn2 = m.group(2).strip()
+ cat_file(fn2)
+ elif cmd == "q": # quit
+ sys.exit(0)
+ elif cmd == "cd": # chdir
+ dir = m.group(2).strip()
+ os.chdir(dir)
+ else: # skip all others
+ pass
+ else:
+ if func_rc.search(ln): # function header
+ proc_func(f, ln)
+ else: # normal sql
+ sys.stdout.write(ln)
+ sys.stdout.write("\n")
+
+def main():
+ global cf_ndoc
+
+ try:
+ opts, args = getopt.gnu_getopt(sys.argv[1:], 'h', ['ndoc'])
+ except getopt.error, d:
+ print d
+ usage(1)
+ for o, v in opts:
+ if o == "-h":
+ usage(0)
+ elif o == "--ndoc":
+ cf_ndoc = 1
+ for fn in args:
+ cat_file(fn)
+
+if __name__ == '__main__':
+ main()
+