Phân tích câu lệnh SELECT SQL

Một phần của tài liệu NGHIÊN CỨU NGÔN NGỮ LẬP TRÌNH PYTHON VÀ ỨNG DỤNG PHÂN TÍCH MỘT SỐ CÚ PHÁP ĐƠN GIẢN (Trang 57)

3. ỨNG DỤNG PHÂN TÍCH MỘT SỐ CÚ PHÁP ĐƠN GIẢN

3.4.Phân tích câu lệnh SELECT SQL

Bộ phân tích đơn giản nhằm trích xuất thông tin table và column từ câu lệnh SELECT.

Cấu tạo

SELECT

<danh sách columns> FROM

<danh sách tables> WHERE

<danh sách điều kiện – chứa các biểu thức so sánh và câu lệnh select>

Sau đây là đoạn mã định nghĩa cho đối tượng phân tích simpleSQL.

Do đoạn code khá dài nên để thuận tiện, ta sẽ giải thích trực tiếp trong đoạn mã. # import các đối tượng sử dụng

from pyparsing import Literal, CaselessLiteral, Word, Upcase, delimitedList, Optional, \ Combine, Group, alphas, nums, alphanums, ParseException, Forward, oneOf,

quotedString, \

ZeroOrMore, restOfLine, Keyword

# Định nghĩa các SQL tokens

# Đối tượng kiểu Forward sẽ cho phép sử dụng toán tử << để bổ sung thêm thành phần theo đúng thứ tự

selectStmt = Forward()

# Keyword cho phép so khớp chính xác với nghĩa keyword, có nghĩa nó phải theo sau bởi một kí tự không phải keyword.

selectToken = Keyword("select", caseless=True) fromToken = Keyword("from", caseless=True)

# alphas = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' # alphanums = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW...

ident = Word( alphas, alphanums + "_$" ).setName("identifier")

# delimitedList nối các ident với nhau theo .

columnName = Upcase( delimitedList( ident, ".", combine=True ) )

# Group sẽ nhóm các kết quả về dạng 0,1 hoặc n phần tử trong danh sách

columnNameList = Group( delimitedList( columnName ) )

tableName = Upcase( delimitedList( ident, ".", combine=True ) ) tableNameList = Group( delimitedList( tableName ) )

# Mệnh đề điều kiện

whereExpression = Forward()

# Định nghĩa các phép kết trong biểu thức bool

and_ = Keyword("and", caseless=True) or_ = Keyword("or", caseless=True) in_ = Keyword("in", caseless=True) E = CaselessLiteral("E")

# Định nghĩa các toán tử

binop = oneOf("= != < > >= <= eq ne lt le gt ge", caseless=True)

# Định nghĩa âm dương

arithSign = Word("+-",exact=1) (adsbygoogle = window.adsbygoogle || []).push({});

# Định nghĩa văn phạm một giá trị thực ( có dấu chấm động)

realNum = Combine( Optional(arithSign) + ( Word( nums ) + "." + Optional( Word(nums) ) | ( "." + Word(nums) ) ) + Optional( E + Optional(arithSign) + Word(nums) ) )

# Định nghĩa văn phạm số nguyên

intNum = Combine( Optional(arithSign) + Word( nums ) + Optional( E + Optional("+") + Word(nums) ) )

# Giá trị của columns

columnRval = realNum | intNum | quotedString | columnName # need to add support for alg expressions

# Mệnh đề điều kiện chứa : # - column <op> value

# - column IN (sanh sách value) # - column IN (một câu lệnh select) # - (Một mệnh đề điều kiện con)

whereCondition = Group(

( columnName + binop + columnRval ) |

( columnName + in_ + "(" + delimitedList( columnRval ) + ")" ) | ( columnName + in_ + "(" + selectStmt + ")" ) |

( "(" + whereExpression + ")" ) )

# Một mệnh đề điều kiện là kết hợp AND hoặc OR các mệnh đề điều kiện con

whereExpression << whereCondition + ZeroOrMore( ( and_ | or_ ) + whereExpression )

# Định nghĩa toàn bộ văn phạm

selectStmt << ( selectToken + ( '*' | columnNameList ).setResultsName( "columns" ) + fromToken +

tableNameList.setResultsName( "tables" ) +

Optional( Group( CaselessLiteral("where") + whereExpression ), "" ).setResultsName("where") )

simpleSQL = selectStmt

# Bõ qua các chú thích trên cùng 1 dòng

oracleSqlComment = "--" + restOfLine simpleSQL.ignore( oracleSqlComment )

Thực hiện test và kiểm tra kết quả def test( str ):

print str,"->" try:

tokens = simpleSQL.parseString( str ) print "tokens = ", tokens

print "tokens.columns =", tokens.columns print "tokens.tables =", tokens.tables print "tokens.where =", tokens.where except ParseException, err:

print " "*err.loc + "^\n" + err.msg print err

print

test( "SELECT * from XYZZY, ABC" ) SELECT * from XYZZY, ABC ->

tokens = ['select', '*', 'from', ['XYZZY', 'ABC'], ''] tokens.columns = *

tokens.tables = ['XYZZY', 'ABC'] tokens.where = [''] (adsbygoogle = window.adsbygoogle || []).push({});

test( "select * from SYS.XYZZY" ) select * from SYS.XYZZY ->

tokens = ['select', '*', 'from', ['SYS.XYZZY'], ''] tokens.columns = *

tokens.tables = ['SYS.XYZZY'] tokens.where = ['']

test( "Select A from Sys.dual where a in ('RED','GREEN','BLUE') and b in (10,20,30)" )

Select A from Sys.dual where a in ('RED','GREEN','BLUE') and b in (10,20,30) ->

tokens = ['select', ['A'], 'from', ['SYS.DUAL'], ['where', ['A', 'in', '(', "'RED'", "'GREEN'", "'BLUE'", ')'], 'and', ['B', 'in', '(', '10', '20', '30', ')']]]

tokens.columns = ['A']

tokens.tables = ['SYS.DUAL']

tokens.where = [['where', ['A', 'in', '(', "'RED'", "'GREEN'", "'BLUE'", ')'], 'and', ['B', 'in', '(', '10', '20', '30', ')']]]

test( "Select A,b from table1,table2 where table1.id eq table2.id -- test out

comparison operators" )

Select A,b from table1,table2 where table1.id eq table2.id -- test out comparison operators -> tokens = ['select', ['A', 'B'], 'from', ['TABLE1', 'TABLE2'], ['where', ['TABLE1.ID', 'eq',

'TABLE2.ID']]]

tokens.columns = ['A', 'B']

tokens.tables = ['TABLE1', 'TABLE2']

Một phần của tài liệu NGHIÊN CỨU NGÔN NGỮ LẬP TRÌNH PYTHON VÀ ỨNG DỤNG PHÂN TÍCH MỘT SỐ CÚ PHÁP ĐƠN GIẢN (Trang 57)