SQLの規約チェックが必要になる局面があって
うまいところPythonと正規表現で対処できないか試行錯誤した自分向けメモ。
Excelのマクロで規約違反検出を行っているのですが
これが遅い上に端末CPUを長時間100%専有するという、非効率極まりなく
また誤検知も多く使い勝手の悪いもので
で、Pythonで書き換えてJenkinsで自動実行する仕組みにしました。
さまざま40ケース程度の規約チェックを書いたのですが
前処理が必要なものもあったり、直接正規表現を投げて解決する様々でした。
規約以前に構文ミスがあるものの検出は考えることも多いものでした。
ちょっとだけサンプルコードを記録しておきます。
DELETEの直後にFROMが来ないSQL
import re
a = 'DELETE FROM aaaa\n'
b = 'DELETE bbbbb\n'
r = re.compile(r'(?=.*DELETE)(?!.*FROM).*$')
for x in r.finditer(a):
print(x)
for x in r.finditer(b):
print(x)
<_sre.SRE_Match object; span=(0, 12), match='DELETE bbbbb'>
DELETE構文でWHEREを指定していないSQLを検出
a = 'DELETE FROM aaaa WHERE\n'
b = 'DELETE FROM bbbbb\n'
r = re.compile(r'(?=.*DELETE\b)(?!.*WHERE\b).*$')
for x in r.finditer(a):
print(x)
for x in r.finditer(b):
print(x)
<_sre.SRE_Match object; span=(0, 17), match='DELETE FROM bbbbb'>
関数を使った語句にASで再度名前を定義していないSQL
#SQLS = ['SELECT LEFT(ALPHA,3) AS B FROM SYSIBM.SYSDUMMY1',
# 'SELECT LEFT(ALPHA,4) FROM SYSIBM.SYSDUMMY1',]
SQLS = ['SELECT LEFT(ALPHA,3) AS B FROM SYSIBM.SYSDUMMY1',
'SELECT LEFT(UTF16_VAR, 2, CODEUNITS16) AS A, LEFT(UTF16_VAR, 2, CODEUNITS32) B, HEX (LEFT(UTF16_VAR, 2, OCTETS)) AS C FROM SYSIBM.SYSDUMMY1',
'SELCT * FROM A']
r = re.compile(r'.*\(.+\)\s(?!AS)')
for sql in SQLS:
for x in r.finditer(str(sql)):
print(x)
<_sre.SRE_Match object; span=(0, 77), match='SELECT LEFT(UTF16_VAR, 2, CODEUNITS16) AS A, LEFT>