Опубликован: 25.07.2012 | Уровень: специалист | Доступ: платный
Дополнительный материал 1:

Приложение А. Пример генератора пакетов PL/SQL

< Лекция 9 || Дополнительный материал 1: 1234

А теперь посмотрим на код, который будет сгенерирован для таблицы equipment. Поля таблицы equipment следующие:

  • id (идентификатор),
  • tag_number (номер ярлыка оборудования),
  • model (наименование модели),
  • description (краткое описание назначения оборудования),
  • type_id (идентификатор типа оборудования, является внешним ключом).

Следующий код можно добавить в событие кнопки для настольного приложения или событие запуска консольного приложения:

//Объявление таблицы, его названия и количества полей
DBTable table = new DBTable();
table.TableName = "equipment";
table.FieldCount = 4;

//Метаданные для простоты примера заполняются напрямую в коде.
//Однако их можно считывать и из базы данных или файла XML.
table.FieldName = new string[table.FieldCount];
table.FieldTypeName = new string[table.FieldCount];
table.FieldLength = new string[table.FieldCount];

table.FieldName[0] = "tag_number";
table.FieldTypeName[0] = "varchar2";
table.FieldLength[0] = "100 char";

table.FieldName[1] = "model";
table.FieldTypeName[1] = "varchar2";
table.FieldLength[1] = "100 char";

table.FieldName[2] = "description";
table.FieldTypeName[2] = "varchar2";
table.FieldLength[2] = "200 char";

table.FieldName[3] = "type_id";
table.FieldTypeName[3] = "number";
table.FieldLength[3] = "";

table.defaultOrderString = "id";

//Указывается путь и часть названия файла вида:
//"A:\Result\equipment_" для вывода результатов.
//К нему впоследствии добавляется часть названия 
//файла в зависимости от типа сгенерированного кода:
//A:\Result\equipment_Objects.txt
//A:\Result\equipment_PackageSpec.txt
//A:\Result\equipment_PackageBody.txt
table.filesPath = @"A:\Result\" + table.TableName + "_";

//Вызывается конструктор для осуществления генерации кода
CodeGenerator cg = new CodeGenerator(table);
    
Пример A.9.

После запуска будет сгенерировано три файла.

Файл equipment_Objects.txt:

create table equipment ( 
id            number primary key,
tag_number            varchar2(100 char),
model            varchar2(100 char),
description            varchar2(200 char),
type_id            number,
update_date            date,
update_user_id            number
)

create sequence seq_equipment
start with 1
maxvalue 999999999999999999999999999
minvalue 1
nocycle
nocache
noorder
    
Пример A.10.

Файл equipment_PackageSpec.txt:

create or replace package pkg_equipment as 

    --------function to create search query------------------
    function fun_search_query(
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number
    ) return varchar2;

    --------procedure to save------------------
    procedure prc_save(p_id number,
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number,
        p_update_user_id in number);

    --------search procedure------------------
    procedure prc_search(
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number,
        p_page in number,
        p_pagesize in number,
        p_order_by varchar2,
        p_order_type varchar2,
        p_recordset out types.ref_cursor);

    --------count procedure------------------
    procedure prc_count(
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number,
        p_pagesize in number,
        p_recordset out types.ref_cursor);

    --------show one item procedure ------------------
    procedure prc_show_by_id(p_id number,  p_recordset out types.ref_cursor );

    --------delete procedure ------------------
    procedure prc_delete(p_id number);

end pkg_equipment;
/
    
Пример A.11.

Файл equipment_PackageBody.txt:

create or replace package body pkg_equipment as 
    const_sqltxt constant varchar2(1000 char):= 'select '||
                ' id,tag_number, model, description, type_id, update_date, update_user_id'|| 
                ' from equipment tbl where 1=1 '; 

    --------function to create search query------------------
    function fun_search_query(
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number
        ) return varchar2 is
        p_wheretxt varchar2(4000);
    begin
        --------------equals------------------------
        p_wheretxt := p_wheretxt || pkg_lib.fun_add_equal_m1('tbl.type_id',p_type_id);

        --------------likes------------------------
        p_wheretxt := p_wheretxt || pkg_lib.fun_add_like('tbl.tag_number',p_tag_number);
        p_wheretxt := p_wheretxt || pkg_lib.fun_add_like('tbl.model',p_model);
        p_wheretxt := p_wheretxt || pkg_lib.fun_add_like('tbl.description',p_description);
        
        return const_sqltxt||p_wheretxt;
    end;

    --------procedure to save------------------
    procedure prc_save(p_id number,
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number,
        p_update_user_id in number) is 
    begin
        if p_id > 0 then 
            update equipment set
                tag_number = p_tag_number,
                model = p_model,
                description = p_description,
                type_id = p_type_id,
                update_user_id = p_update_user_id,
                update_date = sysdate
            where id = p_id;
            commit;
        else
            insert into equipment(id,tag_number, model, description, type_id, update_date, 
             update_user_id)
            values (seq_equipment.nextval,p_tag_number, p_model, p_description,
             p_type_id, sysdate, p_update_user_id);
            commit;
        end if;
    end;

    --------search procedure------------------
    procedure prc_search(
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number,
        p_page in number,
        p_pagesize in number,
        p_order_by varchar2,
        p_order_type varchar2,
        p_recordset out types.ref_cursor) is 
            sqltxt varchar2(4000);
            p_sqltxt varchar2(4000);
            p_sqltxt_page varchar2(4000);
            p_startpage number;
            p_maxpage number;
            p_ordersqltxt varchar2(1000);
    begin
        p_startpage := p_pagesize*(p_page-1);
        p_maxpage := p_pagesize*p_page;
        p_sqltxt := fun_search_query(p_tag_number, p_model, p_description, p_type_id);
        p_ordersqltxt := pkg_lib.fun_sorting_query(p_order_by,p_order_type,'tbl.id');
        p_sqltxt_page := 'select * from (select s1.*, rownum rnum from ('||p_sqltxt|| p_ordersqltxt|| ') s1) ' ||
                'where rnum<=:max_row_to_fetch and rnum > :min_row_to_fetch ' || p_ordersqltxt;
        open p_recordset for p_sqltxt_page using p_maxpage,p_startpage;
    end;

    --------count procedure------------------
    procedure prc_count(
        p_tag_number in varchar2,
        p_model in varchar2,
        p_description in varchar2,
        p_type_id in number,
            p_pagesize in number,
            p_recordset out types.ref_cursor) is 
        p_sqltxt varchar2(4000);
    begin
        p_sqltxt := fun_search_query(p_tag_number, p_model, p_description, p_type_id);
        p_sqltxt := 'select count(1) cnt, ceil(count(1)/:p_pagesize) pagecount from ('||p_sqltxt||') ';
        open p_recordset for p_sqltxt using p_pagesize;
    end;

    --------show one item procedure ------------------
    procedure prc_show_by_id(p_id number,  p_recordset out types.ref_cursor ) is 
    begin
        if p_id > 0 then
            open p_recordset for
            const_sqltxt || ' and tbl.id = :p_id' using p_id;
        end if;
    end;

    --------delete procedure ------------------
    procedure prc_delete(p_id number) is 
        t_var number;
    begin
        select count(1) into t_var from equipment where id = p_id;
        if t_var > 0 then
            delete from equipment where id = p_id;
        commit;
        end if;
    end;

end pkg_equipment;
/
    
Пример A.12.

Для того чтобы сгенерировать 170 строк программного кода, потребовалось создать генератор объемом более 500 строк, то есть в три раза больше. Может показаться, что генерировать код сложнее, чем писать вручную. Однако, если вам надо разработать еще 250-300 схожих пакетов, то это будет около 50000 строк кода. И здесь становится совершенно ясно, что гораздо удобнее и быстрее разработать генератор, ввести описания всех таблиц и сгенерировать за короткое время все 50000 строк программного кода. И это будет стандартный шаблонный код, который практически не содержит ошибок.

< Лекция 9 || Дополнительный материал 1: 1234
Дмитрий Клочков
Дмитрий Клочков
Россия, Рубцовск
Волков Олег
Волков Олег
Украина, Днепропетровск