Trong bài báo trước [9], chúng tôi đã
đề xuất một tiểu ngôn ngữ truy vấn có yếu tố
thời gian SubTSQL để truy vấn và thao tác dữ
liệu trên cơ sở dữ liệu thời gian. Bài báo này
chúng tôi sử dụng mã nguồn mở Lex và Yacc
để xây dựng một trình biên dịch, trình biên
dịch này làm công việc biên dịch câu truy
vấn thời gian thành câu SQL trong Oracle.
Một trình biên dịch như thế dễ dàng tạo lập
và giảm tải cho người lập trình
8 trang |
Chia sẻ: oanhnt | Lượt xem: 1473 | Lượt tải: 1
Bạn đang xem nội dung tài liệu Đề tài Biên dịch câu truy vấn thời gian, thực thi trên hệ quản trị cơ sở dữ liệu, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Khoa học - kĩ thuậät
37
*
TÓM TẮT:
Trong bài báo trước [9], chúng tôi đã
đề xuất một tiểu ngôn ngữ truy vấn có yếu tố
thời gian SubTSQL để truy vấn và thao tác dữ
liệu trên cơ sở dữ liệu thời gian. Bài báo này
chúng tôi sử dụng mã nguồn mở Lex và Yacc
để xây dựng một trình biên dịch, trình biên
dịch này làm công việc biên dịch câu truy
vấn thời gian thành câu SQL trong Oracle.
Một trình biên dịch như thế dễ dàng tạo lập
và giảm tải cho người lập trình.
ABSTRACT:
In [9] we proposed the temporal
query sublanguage SubTSQL that can work
with temporal database. In this paper, we
present to use Open source code Lex and
Yacc that can support a complier so that the
complier is easily built and reducing the
working of programmer. This complier can
convert temporal queries to Oracle SQL
queries
1. GIỚI THIỆU
Thực tế, nhiều ứng dụng trên cơ sở
dữ liệu (CSDL), mà các đối tượng trong
CSDL đó cần gắn thêm yếu tố thời gian [3].
Ví dụ: những ứng dụng như: ngân hàng, lịch
chuyến bay, quản lý kho hàng, hồ sơ bệnh
viện, thị trường chứng khoán v.v..., thì yếu
tố thời gian gắn với đối tượng
* Khoa Cơng nghệ Thơng tin, Trường Đại học Cơng nghiệp TP.
HCM
là một thực tế (đối tượng thay đổi dữ liệu
theo thời gian), cần có nó để tăng mức
phong phú và ngữ nghĩa của dữ liệu trong
CSDL [4], [5], [9].
Hiện tại, chưa có một hệ quản trị cơ
sở dữ liệu (HQTCSDL) nào hỗ trợ một cách
có hệ thống cho việc truy xuất hay thao tác
dữ liệu trên CSDL hướng thời gian. Ngay
cả Oracle 10g thì những câu lệnh có hỗ trợ
thời gian cũng khá phức tạp, người dùng
cần sử dụng nhiều hàm thư viện trong câu
truy vấn, hơn nữa để có một phiên bản
chính thức của Oracle 10g tốn chi phí rất
cao. Câu truy vấn có yếu tố thời gian, nếu
được viết theo cú pháp của một HQTCSDL
thì phức tạp (xem câu truy vấn trong mục
4.1), ngay cả đối với lập trình viên chuyên
nghiệp. Để người dùng dễ dàng viết câu
truy vấn thời gian, cần xây dựng một trình
biên dịch có tính hệ thống, cũng như dễ
dàng mở rộng nó để biên dịch cho nhiều
dạng câu truy vấn khác. Nếu viết một trình
biên dịch như thế theo truyền thống, tốn
kém nhiều chi phí. Do vậy, sử dụng phần
mềm mã nguồn mở (PMMNM) là một
phương pháp khả thi để xây dựng trình biên
dịch. Hơn nữa, Thủ tướng chính phủ đã phê
duyệt Dự án tổng thể ứng dụng và phát
triển PMMNM tại Việt Nam giai đoạn
2004-2008 (Quyết định số 235/QĐ-TTg
ngày 02/02/2004), một trong những
nội dung quan trọng của dự án là đẩy mạnh
BIÊN DỊCH CÂU TRUY VẤN THỜI GIAN,
THỰC THI TRÊN HỆ QUẢN TRỊ CƠ SỞ DỮ LIỆU
Phạm Văn Chung*
Khoa học - kĩ thuậät
38
việc ứng dụng các PMMNM trong triển
khai các ứng dụng công nghệ thông tin tại
các đơn vị, các tổ chức nhà nước cũng như
trong các doanh nghiệp [8].
Bài báo này sử dụng PMMNM Lex
và Yacc để xây dựng bộ văn phạm cho tiểu
ngôn ngữ SubTSQL, mà chúng tôi đã để
xuất trước đây, nó có cú pháp đơn giản gần
như câu truy vấn thông thường (chi tiết
SubTSQL xem trong [9]), và biên dịch câu
truy vấn SubTSQL, thành câu truy vấn theo
cú pháp của Oracle, sau đó dùng thư viện
OCI để kết nối HQTCSDL Oracle qua lập
trình trên C++. Rộng hơn, có thể truy vấn
dữ liệu theo thời gian trên bất kỳ
HQTCSDL nào, miễn là ngôn ngữ dùng để
lập trình cho phép kết nối đến HQTCSDL
đó. Phần còn lại của bài báo gồm có : Phần
2, xây dựng trình biên dịch bằng Lex và
Yacc. Phần 3, kết nối CSDL qua thư viện
OCI. Phần 4, Hiện thực biên dịch câu truy
vấn thời gian trên CSDL bệnh viện và cuối
cùng là kết luận trong phần 5.
2. XÂY DỰNG TRÌNH BIÊN
DỊCH DÙNG LEX VÀ YACC
Xây dựng trình biên dịch
Xây dựng một trình biên dịch theo
truyền thống (thông thường) thường tốn rất
nhiều công sức. Các bước cơ bản mà một
trình biên dịch thông thường phải thực hiện:
- Đọc chuỗi nhập và tách thành các
token.
- Dựa vào văn phạm và các token
tiến hành xây dựng cây phân tích cú pháp .
- Dựa vào cây phân tích cú pháp để
sinh ra mã.
Các bước xây dựng trình biên dịch
được minh họa như hình 1. Trong hình này,
chuỗi nhập sẽ được chuyển qua bộ phân
tích từ vựng để phân tích thành các token,
sau đó các token sẽ được chuyển sang bộ
phân tích cú pháp, tại đây dựa vào văn
phạm và các token, nó tiến hành xây dựng
cây phân tích cú pháp. Cuối cùng, dựa vào
cây phân tích cú pháp, bộ sinh mã sẽ sinh
id3
Chuỗi nhập a = b + c * d
Token id1 = id2 + id3 * id4
Bộ phân tích cú pháp
Cây cú pháp =
Bộ sinh mã
id1 +
*
id4
id2
Sinh mã load id3
mul id4
add id2
store id1
Hình 1. Các bước mà một trình biên dịch thơng thường thực hiện
Bộ phân tích từ vựng
Khoa học - kĩ thuậät
39
mã tương ứng. Bài báo sử dụng Lex và
Yacc là hai PMMNM khá thông dụng, qui
trình xây dựng trình biên dịch được trình
bày trong những phần sau .
Xây dựng trình biên dịch dùng
LEX và YACC
Lex tạo ra bộ phân tích từ vựng với
mã C/C++ hoặc Java. Lex dùng các mẫu
(pattern) để so khớp với chuỗi nhập và biến
đổi chuỗi nhập thành các token tương ứng.
Một token có một mã riêng biệt nhằm đơn
giản hoá công việc xử lý. Khi Lex nhận ra
các danh hiệu (id) trong dòng dữ liệu vào,
nó nhập chúng vào bảng danh biểu. Bảng
danh biểu chứa các thông tin khác như kiểu
dữ liệu (integer, real,…) và vị trí của biến
trong bộ nhớ. Một khi danh hiệu được sử
dụng, các thông tin liên quan đến nó được
truy xuất thông qua chỉ mục trong bảng
này.
Yacc tạo ra bộ phân tích cú pháp với
mã C/C++ hoặc Java. Yacc dùng các luật
văn phạm mà mỗi luật cho phép phân tích
các token từ kết quả của Lex và tạo ra cây
phân tích cú pháp. Một cây phân tích cú
pháp áp đặt cấu trúc có thứ tự lên các
token. Việc tạo ra cây phân tích cú pháp là
một bước quan trọng mà một trình biên dịch
phải thực hiện như trong hình 1.
Quy trình xây dựng một trình biên
dịch sử dụng Lex và Yacc [1],[4] được
trình bày như hình 4. Giả sử, cần viết một
trình biên dịch có tên là bas. Dùng trình
sọan thảo (có thể là Parser Generator 2,
chép tự do trên Internet), trước tiên, xác
định tất cả các luật, kết hợp với các mẫu
và đặt chúng trong tập tin bas.l. cho Lex.
Tiếp đến viết các luật văn phạm vào tập
tin bas.y cho YACC.
Nhiệm vụ của Yacc là đọc các luật
văn phạm và định nghĩa các token, ghi
chúng vào tập tin bas.y và sinh ra bộ phân
tích cú pháp đặt vào tập tin y.tab.c, các
token cũng được định nghĩa trong tập tin
y.tab.h. Nhiệm vụ của Lex là đọc các mô
tả mẫu trong tập tin bas.l và các định nghĩa
token trong tập tin y.tab.h để tạo ra bộ
phân tích từ vựng ghi vào tập tin Lex.yy.c.
Cuối cùng, bộ phân tích từ vựng và bộ phân
tích cú pháp được biên dịch (dùng trình biên
dịch C/C++ hoặc Java), tạo ra tập tin thực
thi bas.exe.
Mỗi luật văn phạm khai báo trong
tập tin bas.y đều có một hành động ngữ
nghĩa tương ứng. Hành động ngữ nghĩa
đóng vai trò như một như bộ sinh mã. Quá
trình sinh mã có nhiều mức, có thể sinh mã
trung gian hoặc sinh ra một mã khác, mã
máy là cấp sinh mã thấp nhất, trong bài báo
này sẽ sinh ra mã trung gian là câu truy vấn
theo cú pháp của Oracle.
Xây dựng bộ phân tích từ vựng sử
dụng Lex có cấu trúc gồm 3 khối như hình 2:
%{
Các khai báo C (C declaration)
%%
Các luật Lex (Lex rules)
%%
Phần mã C (Additional C code)
Hình 2: Cấu trúc các khối cho Lex
Trong hình 2, khối khai báo C được
bắt đầu bởi %{ và kết thúc bởi }%; khối
luật Lex bắt đầu bởi %% và kết thúc bởi
%%; khối mã C viết cuối cùng.
Tương tự, xây dựng bộ phân tích cú
pháp sử dụng Yacc gồm 4 khối, các khối
được phân cách bởi các ký hiệu đóng mở
khối như hình 3, chi tiết về mỗi khối cho
mỗi cấu trúc, xem trong [1],[4],[7].
%{
Các khai báo C (C declarations)
%}
Các khai báo Yacc (Yacc declarations)
Khoa học - kĩ thuậät
40
Chương trình nguồn
Trình biên dịch của Host language
Tập tin đối tượng
Liên kết với OCI
Ứng dụng
Thư viện OCI
Oracle Sever
%%
Phần văn phạm (Grammar rules)
%%
Phần mã C (Additional C code)
Hình 3: Cấu trúc các khối cho Yacc
3. KẾT NỐI CƠ SỞ DỮ LIỆU
DÙNG THƯ VIỆN OCI
Tiến trình phát triển một ứng dụng
OCI
Oracle là một hệ quản trị cơ sở dữ
liệu lớn có bề dầy thời gian và có uy tín.
Tuy nhiên để sử dụng trọn gói, người dùng
phải mất chi phí khá lớn. Thay vì phải mua
trọn gói, người dùng chỉ mua hệ quản trị cơ
sở dữ liệu, khi đó chi phí sẽ giảm đáng kể.
Việc xây dựng các công cụ để kết
nối cơ sở dữ liệu trên Oracle bằng ngôn ngữ
C (C được coi như là một host language)
dựa vào các hàm OCI [6] có sẵn trong
Oracle là một giải pháp khả thi, vì chính
Oracle cũng sử dụng OCI để xây dựng một
số công cụ cho nó.
OCI có thư viện khá phong phú, cho
phép người dùng phát triển các ứng dụng
truy cập dữ liệu không thủ tục của SQL
bằng lập trình thủ tục trên C/Java. OCI hỗ
trợ tất cả các câu lệnh định nghĩa dữ liệu,
thao tác dữ liệu, truy vấn, khả năng điều
khiển chuyển tác mà có sẵn trong Oracle.
Hình 5 minh họa tiến trình phát triển một
ứng dụng OCI.
Yacc
Lex
Trình biên
dịch
C/C++
y.tab.c
bas.exe
Lex.yy.c
bas
y.tab.h
bas.y
bas.l
Hình 4. Quy trình xây dựng trình biên dịch sử
dụng Lex và Yacc
Hình 5: Tiến trình phát triển một ứng dụng
OCI
Khoa học - kĩ thuậät
41
Trong hình 5, từ chương trình nguồn,
tiến hành biên dịch bằng một host
language, để tạo ra các tập tin đối tượng,
các tập tin này tiếp tục được liên kết với thư
viện OCI để tạo ứng dụng, và ứng dụng có
khả năng truy xuất đến CSDL Oracle
server.
Các bước lập trình bằng OCI
Để kết nối CSDL dùng thư viện
OCI, cần thực hiện các bước sau: khởi tạo
các tiến trình, khởi tạo môi trường làm việc,
cấp phát các handle và các cấu trúc dữ liệu
cần thiết và kết nối với CSDL Oracle
server. Bắt đầu phiên làm việc, cấp phát
câu lệnh SQL và truy xuất dữ liệu. Kết thúc
phiên làm việc, người dùng ngắt kết nối với
Oracle server, khi đó cấu trúc dữ liệu và
các handle được giải phóng. Hoạt động của
OCI được minh họa trong hình 6. Trong
hình này, bước xử lý câu lệnh SQL và truy
xuất dữ liệu là khá quan trọng. Một trong
hầu hết những nhiệm vụ phổ biến của một
chương trình OCI là chấp nhận và xử lý câu
lệnh SQL, một khi các handle cần thiết đã
được cấp phát và đã kết nối được với
Oracle server. Đồng thời với mỗi bước trên,
OCI cung cấp các hàm cần thiết tương ứng
cho xử lý câu lệnh SQL, chi tiết coi trong
[6].
4. ỨNG DỤNG
Chúng tôi đã cài đặt thử nghiệm
những câu truy vấn có yếu tố thời gian trên
môi trường Visual C++ với dữ liệu thực của
bệnh viện Nhân dân Gia Định-TP.HCM, và
có những kết qủa tốt.
4.1 Cú pháp của câu truy vấn
SubTSQL
Để thực hiện biên dịch câu truy vấn
bằng mã nguồn mở, phần này nhắc lại một
số ý cơ bản về SubTSQL, chi tiết có thể
xem trong [9]. Dữ liệu thời gian được cập
nhật trong những bảng dữ liệu của mô hình
quan hệ truyền thống, trong mỗi bảng nếu
có dữ liệu thời gian thì thêm vào 2 cột
v_begin (thời gian bắt đầu của dữ liệu được
sinh ra), và v_end (thời gian kết thúc). Nói
một cách khác dữ liệu (hay sự kiện) được
ghi trong bảng có giá trị đúng trong khoảng
thời gian từ v_begin đến v_end (xem bảng
patient dưới đây.
Câu truy vấn thời gian SubTSQL
tương tự như những câu SQL thông thường,
chỉ thêm một mệnh đề WHEN để thao tác
yếu tố thời gian, yếu tố thời gian là vị trí
tương đối giữa hai khoảng thời gian v_begin
và v_end và nó tuân theo những tân từ trong
[2], cụ thể là những tân từ: BEFORE,
AFTER, DURING, CONTAINS, OVERLAPS,
Khởi tạo tiến trình
Khởi tạo mơi trường
Định vị các handle
Kết nối với server
Gửi câu SQL và xử lý
Ngắt kết nối
Giải phĩng các handle và cấu trúc dữ liệu
Hình 6: Những bước hoạt động của OCI
Khoa học - kĩ thuậät
42
MEETS, STARTS, FINISHES, và EQUALS.
Và sau đây là một số ví dụ cụ thể về câu truy
vấn thời gian.
- Câu truy vấn SELECT, mệnh đề
WHEN dùng tân từ ‚DURING‛
SELECT manv, Hoten, V_begin,
V_end FROM NhanVien
WHEN NhanVien DURING
(25/3/2000 , 25/5/2000)
WHERE mapb = 'D8' ;
- Câu truy vấn UPDATE, mệnh đề
WHEN chỉ ra thời gian cần cập nhật
UPDATE drugs set drug= 'dfdsf' WHEN
(25/02/03,05/03/03,'dd/mm/yy')
where p_id>0
- Câu truy vấn DELETE, mệnh đề
WHEN chỉ ra dữ liệu cần xóa trong một
khỏang thời gian.
DELETE from drugs
WHEN(5/02/03,05/03/03,'dd/mm/yy') where
p_id>0
Ví dụ: Cho bảng dữ liệu Patient và
câu truy vấn thời gian như sau
Patient
P_ ID problem department v_begin v_end
J001 P1 D10 14/02/2000 01/03/2000
J001 P2 C2 10/03/2000 31/12/9999
P005 P3 D8 01/04/2000 12/05/2000
R006 P3 D8 13/02/2000 01/06/2000
SELECT p_id, problem, v_begin,
v_end
FROM patient
WHEN patient DURING
(25/3/2000 , 25/5/2000)
WHERE department = 'D8' ;
Câu truy vấn trên cần biên dịch
thành câu Oracle-SQL
SELECT p_id, problem, v_begin,
v_end
FROM patient
WHERE department ='D8' AND
((patient.v_begin)>
to_date(‘25/3/2000’,’’dd/mm/yyyy’)
AND( (patient.v_end) <=
to_date(‘25/5/2000’,’dd/mm/yyyy’))
OR (( patient.v_begin) >=
to_date(‘25/3/2000’,’dd/mm/yyyy’))
AND (patient.v_end)<
to_date(‘25/5/2000’,’dd/mm/yyyy’));
Trong ví dụ này, phần chữ in
nghiêng, đậm trong mệnh đề WHERE của
câu Oracle-SQL chính là nội dung của
mệnh đề WHEN được viết theo những tân
từ so sánh khoảng thời gian như trong [2].
Ví dụ này cho thấy: một câu truy vấn thời
gian được viết bằng câu truy vấn thông
thường thì khá phức tạp, rất dễ mắc lỗi,
ngay cả những lập trình viên chuyên
nghiệp. Do vậy, việc biên dịch câu
SubTSQL bằng mã nguồn mở có ý nghĩa
thiết thực, cũng như câu SubTSQL với cú
pháp đơn giản, dễ thân thiện với người
dùng (Những câu truy vấn thời gian Update
và Delete cũng được biên dịch một cách
tương tự như câu truy vấn Select).
4.2 Kiến trúc trong cài đặt
Để thực hiện cài đặt, chúng tôi kiến
trúc một mô-đun như hình 7, đặt trong
khung hình chữ nhật được viền đậm bằng
đường kép, và nó được đặt trên đỉnh của
HQTCSDL Oracle. Hơn nữa mô-đun này,
nó độc lập với mọi HQTCSDL, nếu được
chỉnh lại một chút trong Yacc để có mã sinh
ra đúng với cú pháp của HQTCSDL cần
dùng.
Khoa học - kĩ thuậät
43
Trong hình 7, tiến trình thực hiện
câu truy vấn bao gồm : Người dùng nhập
một câu lệnh Q, sau đó Lex phân tích Q
thành các token. Yacc phân tích cú pháp
của Q dựa trên cú pháp của SubTSQL. Bất
kì lỗi nào được tìm thấy trong quá trình
phân tích sẽ thông báo. Nếu không có lỗi
thì Q được gửi đến Bộ sinh mã, nó biên
dịch Q thành câu lệnh SQL của Oracle, sau
đó gửi đến hệ quản trị CSDL Oracle thông
qua mô-đun OCI, tại đây nó nhận câu lệnh
SQL- Oracle và thực hiện trên Oracle để
lấy kết quả trả về. Cuối cùng Bộ xử lý xuất
kết quả cho người dùng.
4.3 Giao diện thực hiện câu truy vấn
Hình 8 chỉ ra màn hình giao diện với
người dùng để thực hiện vấn tin trên CSDL
hướng thời gian, được cài đặt trong Visual
C++, người dùng có thể soạn câu truy vấn
trong khung SubTSQL input, sau đó cho kết
nối Oracle bằng nút Connect và thực thi
bằng nút Execute, Kết quả được hiện thị
trong Results. Nếu quá trình biên dịch hay
thực thi trên Oracle có lỗi, thông báo lỗi được
hiển thị trong SQL output/Error output.
5. KẾT LUẬN
Xây dựng ứng dụng bằng sử dụng
mã nguồn mở đã giảm được nhiều chi phí,
hơn nữa mã nguồn mở cho phép có thể áp
dụng xây dựng những ứng dụng khác nhau
trong nhiều lãnh vực. Trong bài báo này, sử
dụng LEX và YACC biên dịch những câu
lệnh để thực hiện những ứng dụng trong mô
hình CSDL hướng thời gian. Và còn có
nhiều mã nguồn mở khác cho phép người
dùng sử dụng theo yêu cầu riêng của mỗi
người mà không vi phạm bản quyền, và đi
vào khá nhiều lãnh vực ứng dụng thiết thực
như: kế toán, phát triển Web, chính phủ
điện tử, công nghệ sinh học, quản trị doanh
nghiệp . . . có thể xem chi tiết trong tập san
[8]. Trong chiều hướng Việt Nam gia nhập
WTO, thì việc phát triển về CNTT dùng mã
nguồn mở là một lối đi dễ dàng có nhiều
hứa hẹn. Công việc tiếp theo của chúng tôi
tiếp tục triển khai ứng dụng mã nguồn mở
để xây dựng thêm những câu truy vấn cho
việc trích yếu thời gian trong mô hình
CSDL hướng thời gian.
Hình 7: Kiến trúc thực hiện câu truy vấn
Oracle
Bộ sinh mã
Bộ xử lý
xuất kết
qủa
Câu truy vấn SubTSQL
Mơ-đun OCI
Lex
Yacc
Kết qủa Báo lỗi
Khoa học - kĩ thuậät
44
TÀI LIỆU THAM KHẢO
[1] Anthony A. Aaby, ‘Compiler
construction using FLex and Bison’, Walla
Walla College, April, 2005.
[2] J.F. Allen, ‘Maintaining
Knowledge about Temporal Intervals’,
Communication of the ACM, 26(11),
November, 1993, 832-843.
[3] C.J. Date, Hugh Darwen,
N.A.Lorentzos, ‘Temporal Data and the
Relation Model’, Morgan Kaufmann
Publishers, 2003.
[4] Bert Hubert, ‘LEX and YACC
primer/How to’, PowerDNS BV, April,
2002.
[5] N. A. Lorentzos, ‘The Interval-
extended Relational Model and its
Application to Valid-time Databases’,
Temporal Databases – Theory, Design and
Implementation, Benjamin/ Cummings
Publishing, 1993, 65-91.
[6] Phil Locke, ‘Oracle Call
Interface Programmer’s Guide’, Oracle
Corporation, 1997.
[7] Thomas Niemann, ‘A compact
guide to LEX & YACC ’,
www.epaperpress.com.
[8] Tập san ‘Hội thảo khoa học ứng
dụng phần mềm mã nguồn mở’, Văn phòng
CNTT- Bộ KH&CN, Sở KH&CN- TP.HCM
13-09-2005.
[9] Phạm văn Chung. Dương Tuấn
Anh, ‚Implementing a Query Sublanguage
for Temporal Clincal database Systems‛,
Proceedings of the MMU International
Symposum on information &
Communications Technologies 2005, 24–
25 November 2005, Malaysia, pp. TS12-
13-16.
Hình 8: Giao diện thực hiện hiện câu truy vấn có
yếu tố thời gian