find_sql_functions: grep sql function signatures.
authorMarko Kreen <markokr@gmail.com>
Wed, 18 Jul 2012 09:31:42 +0000 (12:31 +0300)
committerMarko Kreen <markokr@gmail.com>
Wed, 18 Jul 2012 09:36:00 +0000 (12:36 +0300)
Dumb parser, but works on skytools modules.

scripts/find_sql_functions.py [new file with mode: 0755]

diff --git a/scripts/find_sql_functions.py b/scripts/find_sql_functions.py
new file mode 100755 (executable)
index 0000000..55718cd
--- /dev/null
@@ -0,0 +1,103 @@
+#! /usr/bin/env python
+
+"""Find and print out function signatures from .sql file.
+
+Usage:
+    find_sql_functions.py [-h] [-s] [-p PREFIX] FILE ...
+
+Switches:
+    -h         Show help
+    -p PREFIX  Prefix each line with string
+    -s         Check whether function is SECURITY DEFINER
+"""
+
+import sys, re, getopt
+
+rx = r"""
+^
+create \s+ (?: or \s+ replace \s+ )?
+function ( [^(]+ )
+[(] ( [^)]* ) [)]
+"""
+
+rx_secdef = r"""security\s+definer"""
+
+
+rc = re.compile(rx, re.I | re.M | re.X)
+sc = re.compile(r"\s+")
+rc_sec = re.compile(rx_secdef, re.I | re.X)
+
+def grep_file(fn, cf_prefix, cf_secdef):
+    sql = open(fn).read()
+    pos = 0
+    while 1:
+        m = rc.search(sql, pos)
+        if not m:
+            break
+        pos = m.end()
+
+        m2 = rc.search(sql, pos)
+        if m2:
+            xpos = m2.end()
+        else:
+            xpos = len(sql)
+        secdef = False
+        m2 = rc_sec.search(sql, pos, xpos)
+        if m2:
+            secdef = True
+
+        fname = m.group(1).strip()
+        fargs = m.group(2)
+
+        alist = fargs.split(',')
+        tlist = []
+        for a in alist:
+            a = a.strip()
+            toks = sc.split(a.lower())
+            if toks[0] == "out":
+                continue
+            if toks[0] in ("in", "inout"):
+                toks = toks[1:]
+            # just take last item
+            tlist.append(toks[-1])
+
+        sig = "%s(%s)" % (fname, ", ".join(tlist))
+
+        if cf_prefix:
+            ln = "%s %s;" % (cf_prefix, sig)
+        else:
+            ln = "    %s(%s)," % (fname, ", ".join(tlist))
+
+        if cf_secdef and secdef:
+            ln = "%-72s -- SECDEF" % (ln)
+
+        print ln
+
+def main(argv):
+    cf_secdef = 0
+    cf_prefix = ''
+
+    try:
+        opts, args = getopt.getopt(argv, "hsp:")
+    except getopt.error, d:
+        print 'getopt:', d
+        sys.exit(1)
+
+    for o, a in opts:
+        if o == '-h':
+            print __doc__
+            sys.exit(0)
+        elif o == '-s':
+            cf_secdef = 1
+        elif o == '-p':
+            cf_prefix = a
+        else:
+            print __doc__
+            sys.exit(1)
+
+    for fn in args:
+        grep_file(fn, cf_prefix, cf_secdef)
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
+