11

Xem mã biên dịch có điều kiện: Cái gì sẽ chạy?

Thứ 2 trong loạt bài về biên dịch có điều kiện. 

Trong bài trước (đầu tiên) trong loạt bài của tôi về biên dịch có điều kiện, tôi đã đề cập đến các trường hợp sử dụng và trình bày một số ví dụ đơn giản.

Trong bài đăng này, tôi chỉ cho bạn cách bạn có thể xác nhận mã nào thực sự sẽ được thực thi sau khi biên dịch. Nếu không có điều kiện biên dịch, đây tất nhiên là một bài tập ngớ ngẩn. Mã được thực thi giống với mã bạn thấy trong trình chỉnh sửa của mình.

Nhưng với biên dịch có điều kiện, mã được biên dịch và do đó chạy có thể phụ thuộc vào bất kỳ điều nào sau đây:

  • Phiên bản của cơ sở dữ liệu mà nó được biên dịch
  • Giá trị của cờ biên dịch có điều kiện do người dùng xác định
  • Các giá trị của cờ biên dịch có điều kiện (hệ thống) được xác định trước, như ## plsq1_optimize_level

Có thể hơi lo lắng cho một nhà phát triển khi không hoàn toàn chắc chắn những gì sẽ thực thi, vì vậy chúng tôi cung cấp gói DBMS_PREPROCESSOR, với hai chương trình con của nó:

  • print_post_processed_source - hiển thị mã sau xử lý trên màn hình của bạn
  • get_post_processed_source - trả về mã sau xử lý dưới dạng một mảng.

Thủ tục "in" có ba lần nạp chồng:

1. In văn bản nguồn đã được xử lý sau của một đơn vị PL / SQL được lưu trữ:

DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE ( 
object_type IN VARCHAR2,
schema_name IN VARCHAR2,
object_name IN VARCHAR2);

2. In văn bản nguồn đã qua xử lý của một đơn vị biên dịch:

DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE ( 
source IN VARCHAR2);

3. In văn bản nguồn đã được xử lý sau của bảng INDEX-BY có chứa văn bản nguồn của đơn vị biên dịch:

DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE (
source IN source_lines_t);

Hãy thử nó ra. Mức tối ưu hóa của tôi được đặt thành mặc định: 2. Tôi thực hiện các câu lệnh sau:

CREATE OR REPLACE PROCEDURE post_processed
IS
BEGIN
   $IF $$plsql_optimize_level = 1
   $THEN
      -- Slow and problematic
      NULL;
   $ELSE
      -- Fast and modern and easy
      NULL;
   $END
END post_processed;
/

BEGIN
   DBMS_PREPROCESSOR.print_post_processed_source (
      'PROCEDURE',
      SYS_CONTEXT ('userenv', 'current_schema'),
      'POST_PROCESSED');
END;
/

và tôi thấy kết quả này:

PROCEDURE post_processed
IS
BEGIN
   




      -- Fast and modern and easy
      NULL;
   
END post_processed;

Sau đó, tôi đặt mức tối ưu hóa thành 1 cho quy trình này khi tôi biên dịch lại nó:

ALTER PROCEDURE post_processed COMPILE plsql_optimize_level=1 
/

Đầu ra sau đó thay đổi như sau:

BEGIN
   DBMS_PREPROCESSOR.print_post_processed_source (
      'PROCEDURE',
      SYS_CONTEXT ('userenv', 'current_schema'),
      'POST_PROCESSED');
END;
/

PROCEDURE post_processed
IS
BEGIN
   

      -- Slow and problematic
      NULL;
   



END post_processed;

Hãy xem xét kỹ lưỡng và cẩn thận hai bộ đầu ra này. Lưu ý rằng khoảng trắng (dọc - dòng, và ngang - khoảng trắng) được giữ gìn cẩn thận như thế nào. Đây là điều quan trọng.

Đây là mã sẽ được thực thi. Vì vậy, PL / SQL cần đảm bảo rằng nếu một ngoại lệ được đưa ra và ngăn xếp lỗi hoặc dấu tích lùi được hiển thị / ghi nhật ký, thì số dòng và cột trong các thông báo đó phản ánh những gì bạn thấy trong mã nguồn ban đầu của mình , cụ thể là:

CREATE OR REPLACE PROCEDURE post_processed
IS
BEGIN
   $IF $$plsql_optimize_level = 1
   $THEN
      -- Slow and problematic
      NULL;
   $ELSE
      -- Fast and modern and easy
      NULL;
   $END
END post_processed;

Tôi hy vọng bạn có thể thấy đó là, trên thực tế, là trường hợp.

Tôi có thể cho bạn xem các ví dụ về việc gọi các quá trình nạp chồng khác của thủ tục in, nhưng tôi nghĩ bạn hiểu rõ. Về cơ bản, đây là hành vi tương tự như thủ tục in, nhưng sử dụng hàm get thay thế - và đóng gói vào thủ tục của riêng tôi, thêm số dòng:

CREATE PROCEDURE show_code_for (tp IN VARCHAR2, nm IN VARCHAR2)
IS
   l_postproc_code   DBMS_PREPROCESSOR.source_lines_t;
   l_row             PLS_INTEGER;
BEGIN
   l_postproc_code :=
      DBMS_PREPROCESSOR.get_post_processed_source (
         tp,
         SYS_CONTEXT ('userenv', 'current_schema'),
         nm);
   l_row := l_postproc_code.FIRST;

   WHILE (l_row IS NOT NULL)
   LOOP
      DBMS_OUTPUT.put_line (
            LPAD (l_row, 3)
         || ' - '
         || RTRIM (l_postproc_code (l_row), CHR (10)));
      l_row := l_postproc_code.NEXT (l_row);
   END LOOP;
END;
/

và tôi đặt nó để sử dụng:

BEGIN
   show_code_for ('PROCEDURE', 'POST_PROCESSED');
END;
/

  1 - PROCEDURE post_processed
  2 - IS
  3 - BEGIN
  4 -    
  5 - 
  6 -       -- Slow and problematic
  7 -       NULL;
  8 -    
  9 - 
 10 - 
 11 - 
 12 - END post_processed;

Tôi hy vọng bạn tìm thấy điều này hữu ích.

Tài nguyên

  • Sách trắng toàn diện : một nơi khởi đầu tuyệt vời - và cần đọc - cho bất kỳ ai có kế hoạch sử dụng biên dịch có điều kiện trong mã sản xuất

  • Các tập lệnh biên dịch có điều kiện trên LiveSQL

  • Tim Hall (Oracle-BASE) phạm vi biên dịch có điều kiện

  • Tài liệu biên dịch có điều kiện

  • Bài báo trên Tạp chí Oracle của tôi về chủ đề này

|