Oracle DB, Oracle APEX, Linux etc.

вторник, 25 октября 2016 г.

Oracle Multitenant: Data Pump + DATA_PUMP_DIR = ORA-39001

Основная фича Oracle 12c -- Multitenant -- вместе с удобством администрирования привнесла и проблемы. Одна из них -- невозможность экспорта из и импорта в подключаемые БД, используя создаваемую по умолчанию директорию DATA_PUMP_DIR:

The default Data Pump directory object, DATA_PUMP_DIR, does not work with PDBs. You must define an explicit directory object within the PDB that you are exporting or importing.

При этом вы можете спокойно использовать эту директорию из подключаемой БД, работая с файлами через UTL_FILE. Похоже, проблема в том, что Data Pump фильтрует доступные в БД директории по ORIGIN_CON_ID:

SQL> select origin_con_id
  2    from dba_directories
  3   where directory_name = 'DATA_PUMP_DIR'
  4  /

ORIGIN_CON_ID
-------------
            1

SQL> show con_id

CON_ID
-------------
3 

Проблема решается одним из двух способов:
  1. Создать свою директорию в подключаемой БД и дать права на её чтение и запись отдельному пользователю, если требуется:

    SQL> create directory pdb1_data_pump_dir as '/path/to/dir';
    
    Directory created.
    
    SQL> grant read, write on directory pdb1_data_pump_dir to system;
    
    Grant succeeded.
  2. Удалить директорию DATA_PUMP_DIR в корневом контейнере и создать её там с параметром сессии "_oracle_script"=FALSE, а затем создать её же в каждой подключаемой БД (и в шаблоне БД):
    SQL> conn / as sysdba
    Connected.
    SQL> show con_id
    
    CON_ID
    ----------------
    1
    
    SQL> drop directory data_pump_dir;
    
    Directory dropped.
    
    SQL> alter session set "_oracle_script" = false;
    
    Session altered.
    
    SQL> create directory data_pump_dir as '/path/to/dir';
    
    Directory created.
    
    SQL> grant read, write on directory data_pump_dir to system;
    
    Grant succeeded.
    
    SQL> alter session set container = pdb1;
    
    Session altered.
    
    SQL> create directory data_pump_dir as '/path/to/dir';
    
    Directory created.
    
    SQL> grant read, write on directory data_pump_dir to system;
    
    Grant succeeded.

Читать далее

четверг, 21 июля 2016 г.

ORA-28374, OPEN_NO_MASTER_KEY и другие проблемы, связанные с TDE

Хорошая статья, подробно описывающая проблемы, возникающие с ключами и их хранилищами для Transparent Data Encryption, причины возникновения и решения: Oracle Public Cloud Database Service – ORA-28374: typed master key not found in wallet by Seth Miller.
Читать далее

вторник, 5 мая 2015 г.

ORDS 3.0: Проблема с настройкой подключения к нескольким БД

Один экземпляр Oracle REST Data Services (ORDS) может работать сразу с несколькими базами данных. Для этого необходимо задать настройки для подключения к ним и выбрать метод, по которому ORDS будет определять, к какой БД хочет обращается клиент. Подробней можно прочитать здесь: REST Data Services Installation, Configuration, and Development Guide — 2.1 Configuring Multiple Databases.

Но недавно вышедший ORDS 3.0.0.121 при добавлении настроек для дополнительной БД создаёт неверные файлы конфигурации. Как пример, результат настройки для базы с именем apex40:

$ java -jar ords3.war setup --database apex40
[skipped]
$ cd $APEX_CONFIG_DIR/conf
$ cat apex40.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Tue May 05 01:49:57 EEST 2015</comment>
<entry key="db.password">...</entry>
<entry key="db.username">APEX_PUBLIC_USER</entry>
</properties>
Отсутствуют имя хоста и порт (что в моём случае несущественно), имя службы. Без этой информации ORDS использует настройки подключения по умолчанию из $APEX_CONFIG_DIR/defaults.xml и подключается не к той БД.

Исправить досадный баг просто, достаточно добавить настройки подключения в файлы $APEX_CONFIG_DIR/conf/<имя_БД>*.xml вручную:




Saved on Tue May 05 01:49:57 EEST 2015
...
...
...
...
APEX_PUBLIC_USER

Надеюсь, это поправят в ближайшем обновлении ORDS.

Читать далее

понедельник, 4 мая 2015 г.

Немного камней по дороге к APEX 5.0

Как писал раньше, для начала планировал создать отдельную подключаемую БД, в которой уже потом разворачивать APEX 5.0. Для этого решил создать контейнерную БД Oracle 12.1.0.2.3 (CDB) на Linux 86-64, смигрировать уже имеющуюся холодную не-контейнерную БД (non-CDB) в виде подключаемой (PDB) в новосозданную и на её копию установить новый APEX. Создал и обновил БД, на следующем шаге воспользовался руководством: Multitenant : Migrate a Non-Container Database (CDB) to a Pluggable Database (PDB) in Oracle Database 12c Release 1 (12.1). И это было ошибкой. :)

Как промежуточный результат, получил CDB, в которой APEX уже был установлен в корневом контейнере и мог быть обновлён только для всех контейнеров сразу. Если попытаться обновить его только в одном из контейнеров, то те из них, в которых версия APEX не совпадала с версией в корневом контейнере, просто открывались в ограниченном режиме, оставляя сообщения об ошибках в PDB_PLUG_IN_VIOLATIONS:

> alter session set container=cdb$root

session SET altered.

> select message from pdb_plug_in_violations 
 where type = 'ERROR' 
   and status <> 'RESOLVED';

MESSAGE                                                                                            
----------------------------------------------------------------------------------------------------
APEX mismatch: PDB installed version 4.2.6.00.03 CDB installed version 4.2.5.00.08                   

Поэтому пришлось удалять полученную PDB, затем удалять APEX из CDB (Multitenant : Uninstall APEX from the CDB in Oracle Database 12c Release 1 (12.1)) и создавать PDB как копию non-CDB с установленным APEX заново. Но и на этом всё не закончилось: PDB открывалась со следующей ошибкой:

Sync PDB failed with ORA-65177 during 'alter user APEX_PUBLIC_USER account unlock'

Гугл на это сказал немного, как и MOS. Поскольку в корневом контейнере такого пользователя не обнаружил, а в PDB у него были лишь права DML на FLOWS_FILES.WWV_FLOW_FILE_OBJECTS$, то решил его пересоздать в PDB, не мудрствуя лукаво:

conn / as sysdba
alter session set container=pdb1;
drop user apex_public_user;

На что Oracle ответил:

28014. 00000 -  "cannot drop administrative users"
*Cause:    An attempt was made to drop administrative users.
           Administrative users can be dropped only by SYS during
           migration mode.
*Action:   Try dropping administrative users during migration mode.

Немного погуглив, изменил подход:
alter pluggable database pdb1 close immediate;
alter pluggable database pdb1 open upgrade;
alter session set "_oracle_script"=true;
alter session set container=pdb1;
drop user apex_public_user;
alter pluggable database pdb1 close;
alter pluggable database pdb1 open;
PDB открылась без ошибок. После этого можно было пересоздать пользователя APEX_PUBLIC_USER:
alter session set container=pdb1;
create user apex_public_user identified by apex_public_user;
grant select, insert, update, delete on flows_files.WWV_FLOW_FILE_OBJECTS$ 
  to apex_public_user;
grant connect to apex_public_user;

Пользователь на месте, PDB успешно открыта. Увы, попытка достучаться из ORDS к базе возвращала 503 Service unavailable. В alert.log нашёл «воодушевляющее» сообщение:

ORA-00600: internal error code, arguments: [kpdbAttachSga: bad pdb], [0], [pdb1.workgroup], [], [],[], [], [], [], [], [], []

Поиск на MOS вывел на похожий параметром ORA-00600 баг 20438519 и устраняющий его патч 19972766. После установки последнего наконец-то всё заработало.

Читать далее

понедельник, 20 апреля 2015 г.

Oracle APEX 5.0!

Вот так пару дней поболел и пропустил выход долгожданной новой версии. Ну что, сценарий для изучения теперь проще с Multitenant:
  1. Скачать новый APEX.
  2. Создать БД для тестирования:
    create pluggable database apx5 from tmpl file_name_convert( '/app/oracle/oradata/tmpl', '/app/oracle/oradata/apx5' );
  3. Установить свежий APEX 5.0 и посмотреть, что стало лучше, а что перестало работать. :)

Читать далее

среда, 15 апреля 2015 г.

Oracle Multitenant и ORA-28000

Наткнулся недавно на небольшую проблему — ORDS на Glassfish отказывался создавать подключения к БД, выводя на экран "503 — Service Unavailable" со следующим сообщением в server.log:
The pool named: apex is not correctly configured, error: ORA-28000: the account is locked


Посмотрел пользователя БД в файле конфигурации ORDS для пула apex ${configdir}/ords/conf/apex.xml:
...
<entry key="db.username">APEX_PUBLIC_USER</entry>
...

Настройки для соединения взял из ${configdir}/ords/defaults.xml:
...
<entry key="db.hostname">hostname</entry>
<entry key="db.port">1521</entry>
<entry key="db.servicename">pdb1.workgroup</entry>
...

Подсоединился к pdb1.workgroup, проверил пользователя APEX_PUBLIC_USER — открыт. И вот тут я потратил достаточно много времени, прежде чем вспомнил, что с появлением Multitenant Architecture в Oracle 12c появились общие пользователи. Переключился в корневую БД, и точно — заблокирован APEX_PUBLIC_USER!

alter user apex_public_user account unlock;
alter user apex_public_user identified by ...;

После этого ORDS смог подключиться, проблема была решена.

Читать далее

воскресенье, 22 февраля 2015 г.

Oracle APEX: разбивка на страницы интерактивных отчётов

Благодаря дискуссии на SQL.RU, решил проверить, как на самом деле происходит выдача страницы данных для интерактивного отчёта в Oracle APEX. Использовал версию 4.2.5, но не думаю, что что-то будет сильно отличаться вплоть до 4.1 включительно. Создал приложение с простым интерактивным отчётом, у которого в качестве источника данных был следующий запрос:

select * from emp

Изначально я ставил на то, что движок выполнения отчётов переписывает указанный разработчиком запрос и помимо прочей обёртки добавляет к нему один из известных приёмов по выдаче части отсортированных данных. Например:

select {select list}
  from ( select {select list}, row_number() over( order by {ordering} ) apx$rn 
           from ( {filtering, computing etc.} ) 
          order by {ordering} )
 where apx$rn between :page_min_row and :page_max_row

Результаты отладки меня слегка удивили:


Была слабая надежда, что это не окончательный запрос, и где-то там его ещё дополнительно обернут… Однако, после поиска в исходниках и вдумчивого чтения разврапленного wwv_flow_worksheet.plb я обнаружил, что всё намного печальней: в WWV_FLOW_WORKSHEET.get_report открывается курсор по тексту запроса, в котором нет никакого намёка на первую и последнюю строки страницы. Вместо этого курсор в цикле вхолостую считывается, пока не доходит до первой строки страницы. Затем начинается вывод строк, пока не дойдёт до последней.

Какие из полученных знаний можно сделать выводы:
  1. Каждая следующая страница интерактивного отчёта, к которой перейдёт пользователь, будет требовать чтения всё большего объёма данных. Пользователей нужно учить пользоваться всеми инструментами ИО, такими как фильтры, сортировки и т.п., а не рассматривать его как большую решётку Excel, в которой вместо Page Down можно жать на ссылку к следующей странице отчёта.
  2. Пользоваться настройкой максимального отображаемого количества строк в интерактивных отчётах всё-таки необходимо. Собственно, этому и учит нас документация APEX и другие материалы, как теперь видно — обоснованно. В отличие от границ страницы, ограничение числа строк в текст запроса добавляется и влияет на план выполнения.
  3. Оптимизатор может решить выполнять Ваш тяжёлый запрос для отчёта в режиме ALL_ROWS, несмотря на необходимость для вывода на страницу всего лишь в первых паре сотен строк. Уговорить его этого не делать Вы сможете с трудом, например созданием дополнительного процесса Before Header, в котором будет выставляться явно соответствующий режим:
    execute immediate 'alter session set optimizer_mode = all_rows';
    Кроме того, в WWV_FLOW_WORKSHEET.get_worksheet_report_query при оборачивании текста запроса используется поле WWV_FLOW_WORKSHEETS.sql_hint, название которого намекает на возможное светлое будущее, где разработчику APEX предоставят интерфейс для указания хинтов запросу отчёта.

Читать далее

воскресенье, 19 октября 2014 г.

JasperReports Integration + GlassFish

Делюсь инструкцией по установке сервлета, позволяющего использовать JasperReports из APEX. В качестве контейнера используется GlassFish. По ходу описания я расскажу, как обновить в сервлете JasperReports Library и настроить соединение с Oracle в GlassFish.

Потребуются:
  • установленный APEX (4.2.6);
  • установленный GlassFish (4.1), каталог установки в инструкции обозначен как GLASSFISH_ROOT;
  • JasperReports Library (5.6.0), далее JRL;
  • JasperReports Integration (2.1.0), далее JRI.

Установка и настройка:

  1. Распаковать JRI в какой-либо пустой каталог (далее $JRI_ROOT).
  2. Переписать файлы *.jar из папки $JRI_ROOT/lib в каталог $GLASSFISH_ROOT/glassfish/domains/domain1/lib:
    cp $JRI_ROOT/lib/*.jar $GLASSFISH_ROOT/glassfish/domains/domain1/lib
  3. Извлечь из веб-приложения JRI файл web.xml для указания каталога, в котором будут расположены каталог конфигурационных файлов, каталог отчётов, каталог файлов протокола работы приложения:
    cd $JRI_ROOT
    java -jar bin/truezip.jar cp webapp/JasperReportsIntegration.war/WEB-INF/web.xml web.xml
  4. Изменить в файле web.xml параметр oc.jasper.config.home (тег param-value):
    
      oc.jasper.config.home/path/to/jasperreports/config/dir
    

    Каталог в настройке (далее $JRI_CONF_HOME) должен давать права на чтение и запись пользователю ОС, под которым запускается GlassFish.
  5. Обновить файл web.xml в архиве веб-приложения:
    cd $JRI_ROOT
    java -jar bin/truezip.jar cp web.xml webapp/JasperReportsIntegration.war/WEB-INF/web.xml
  6. Создать каталог $JRI_CONF_HOME, если он ещё не создан, настроить права.
  7. Переписать в этот каталог $JRI_CONF_HOME папки $JRI_ROOT/{conf,logs,reports}.
  8. Зайти в веб-консоль GlassFish и установить приложение: Applications→Deploy. Выбрать архив с обновлённым web.xml.
    Context Root=/jri
  9. Создать JDBC Connection Pool с произвольным именем (далее $POOL_NAME). JDBC→JDBC Connection Pools→New:
    Resource Type: javax.sql.DataSource
    Datasource Classname: oracle.jdbc.pool.OracleDataSource
    Properties→User: DB_USER
    Properties→Password: db_password
    Properties→URL: jdbc:oracle:thin:@your.db.host:1521:oracle_sid
    
  10. Проверить пул, выбрав его и нажав Ping.
  11. Создать JDBC Resource, с которым будет работать приложение. JDBC→JDBC Resource→New:
    JNDI Name: Строка из букв и чисел с префиксом, отделённым косой чертой (например, jdbc/default, jdbc/mydbuser1)
    Pool Name: $POOL_NAME
  12. В файле $JRI_CONF_HOME/conf/application.properties настроить JNDI-префикс и подключения:
    ...
    jndiPrefix=jdbc/
    ...
    [datasource:default]
    type=jndi
    name=default
    # Для ресурса JNDI убирается префикс и указывается оставшаяся строка
    
  13. Распаковать JasperReports Library в какой-либо каталог (далее $JRL_ROOT);
  14. Остановить домен GlassFish в консоли:
    asadmin stop-domain domain1
  15. Обновить библиотеку JasperReports в составе JRI. Для этого перейти в $GLASSFISH_ROOT/glassfish/domains/domain1/applications/JasperReportsIntegration/WEB-INF/lib и выполнить для удаления старой библиотеки:
    chmod u+x _jasper-reports-delete-libs-5.1.0.sh
    ./_jasper-reports-delete-libs-5.1.0.sh
  16. Переписать в $GLASSFISH_ROOT/glassfish/domains/domain1/applications/JasperReportsIntegration/WEB-INF/lib все файлы из каталога $JRL_ROOT/lib и файл $JRL_ROOT/dist/jasperreports-5.6.0.jar.
    cp $JRL_ROOT/lib/* $JRL_ROOT/dist/jasperreports-5.6.0.jar $GLASSFISH_ROOT/glassfish/domains/domain1/applications/JasperReportsIntegration/WEB-INF/lib
  17. Запустить домен GlassFish в консоли:
    asadmin start-domain domain1
  18. Выполнить скрипт $JRI_ROOT/sql/sys_install.sql. Потребуется указать схему БД, в которой будет размещаться API для формирования отчётов из PL/SQL.
  19. Выполнить скрипт $JRI_ROOT/sql/sys_install_acl.sql. Потребуется указать схему БД, в которой будет размещаться API для формирования отчётов из PL/SQL.
  20. Выполнить скрипт $JRI_ROOT/sql/user_install.sql от имени пользователя, в схеме которого будет размещаться API для формирования отчётов из PL/SQL.
  21. Для проверки работоспособности веб-приложения открыть http://<сервер с GlassFish>:<настроенный для приложений порт>/
  22. Для проверки обращений и примера использования JRI из APEX установить приложение из $JRI_ROOT/apex.

Читать далее

понедельник, 19 августа 2013 г.

Плагин TabGrid

Небольшая вариация на тему грида Ext JS в APEX: http://apex.oracle.com/pls/otn/apex/f?p=40749:1
Логин/пароль: demo/demo

Направление развития: фильтры, работающие на сервере.

PS: Есть желание замахнуться на небольшой фреймворк в качестве альтернативы FOEX.
Читать далее

пятница, 31 мая 2013 г.

Oracle: запрос для отображения комментариев к таблице в виде DDL

Простой запрос для получения готовых DDL-операторов COMMENT с комментариями к таблице и её столбцам:

with par as (
  select nvl('&owner', user) owner -- Владелец схемы с таблицей
       , '&table_name' table_name  -- Таблица
    from dual
)
select ddl_stmt 
  from (select p.owner
             , p.table_name
             , '' column_name
             , comments
             , 'comment on table "'||p.owner||'"."'||p.table_name||'" is ''' || comments ||''';'  ddl_stmt
          from par p 
            left join 
               all_tab_comments tc on p.owner = tc.owner and p.table_name = tc.table_name 
         union all
        select c.owner
             , c.table_name
             , c.column_name
             , tc.comments
             , 'comment on column "'||c.owner||'"."'||c.table_name||'"."'||c.column_name||'" is ''' || comments ||''';'  ddl_stmt
          from (select owner, table_name, column_name 
                  from par p natural join all_tab_columns c) c
            left join 
                all_col_comments tc on c.owner = tc.owner and c.table_name = tc.table_name and c.column_name = tc.column_name)
 order by owner, table_name, column_name nulls first
/

Полезен как заготовка в ситуациях, когда нужно создать скрипт добавления или изменения комментариев к таблице.
Читать далее

четверг, 14 марта 2013 г.

Oracle APEX: Remote Debug

Случайно узнал, что можно включить удалённую отладку установкой в URL значения REMOTE для аргумента Debug. При этом подключение для удалённой отладки происходит в самом начале этапов Page Processing и Page Rendering и создаётся к удалённому хосту из переменной REMOTE_ADDR окружения CGI на порт 4000.

В документации об этом почему-то ни слова.

Пользуясь случаем, напоминаю, что уровнем отладки (и количеством выдаваемой информации) можно управлять, используя значения LEVELn для аргумента Debug, где n -- уровень отладки от 1 до 9. По умолчанию, для значения YES используется уровень 4.

Читать далее

четверг, 14 февраля 2013 г.

Oracle APEX: Report Template Preview

Да, я знаю, что обещал заметку о том, как создавать плагин-регион. Но пока я её готовлю, могу предложить описание поиска ошибки в APEX Application Builder и её исправления.

Ошибка заключается в том, что в APEX уже довольно давно поломался предпросмотр шаблонов отчётов.


Для шаблонов страниц работает, для регионов тоже, а отчёты показывают крайне информативное сообщение:
report error: 
ORA-01002: fetch out of sequence

Как всё поправить? Для начала, нужно разобраться, что выполняется на странице. Смотрим в адресную строку:
/apex/f?p=4000:245:7846987198961::::F4000_P245_ID:2451412072364242

Заглядываем в словарь APEX, что там за регионы на странице 245 приложения 4000:
column region_name format a20
column region_id format 999999999999999999999999
column source_type format a15
column region_source format a80
set long 700
select region_name, region_id, source_type, region_source 
  from apex_040200.apex_application_page_regions 
 where application_id = 4000 and page_id = 245
/
REGION_NAME                          REGION_ID SOURCE_TYPE     REGION_SOURCE                                                                  
-------------------- ------------------------- --------------- --------------------------------------------------------------------------------
Breadcrumb                    6539000463209372 Breadcrumb                                                                                       
Template Preview             14562627207747006 PL/SQL          wwv_render_report3.show(                                                         
                                                                   p_query => '                                                                 
                                                               select 1 COL1, ''[...]'' COL2, ''[...]                                           

Template Preview             14573702151806062 HTML/Text       

This page provides a preview of the identified report template.

Template Details 82014114667920662 Report select ROW_TEMPLATE_NAME N, ROW_TEMPLATE_TYPE T from WWV_FLOW_ROW_TEMPLATES preview-report 88449328191587806 Report select 1 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual union select

Судя по названиям и содержимому, нас интересуют регионы с REGION_ID 14562627207747006 и 88449328191587806. Первый выполняет обращение к wwv_render_report3.show, второй, как мы сейчас увидим, служит для хранения настроек, которые используются в этом вызове:
column region_source format a700
set long 700
select region_id, region_source 
  from apex_040200.apex_application_page_regions 
 where region_id in (14562627207747006, 88449328191587806)   
/
REGION_ID REGION_SOURCE
------------------------- --------------------------------------------------------------------------------
        14562627207747006 wwv_render_report3.show(
                              p_query => '
                          select 1 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union
                          select 2 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union
                          select 3 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union
                          select 4 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union
                          select 5 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union
                          select 6 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual
                          order by 1',
                              p_row_template_id => :f4000_p245_id,
                              p_region_id => 88449328191587806
                            );

        88449328191587806 select 1 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual union
                          select 2 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual union
                          select 3 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual union
                          select 4 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual union
                          select 5 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual union
                          select 6 COL1, '[...]' COL2, '[...]' COL3, sysdate COL4 from dual
                          order by 1
Значит, путь наш лежит в wwv_render_report3.show. Чтобы посмотреть, что именно там происходит, потребуется разврапировать тело пакета и установить его в схему APEX. Тело находится в файле reports3.plb.

Затем включить удалённую отладку, для чего потребуется скомпилировать этот пакет с поддержкой отладки. Ещё в рамках подготовки к удалённой отладке потребуется временно изменить содержимое региона 14562627207747006, окружив вызов обращениями к dbms_debug_jdwp:
update wwv_flow_page_plugs 
   set plug_source = q'{dbms_debug_jdwp.connect_tcp('localhost',50001);  
wwv_render_report3.show(
    p_query => '
select 1 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 2 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 3 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 4 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 5 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 6 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual 
order by 1',
    p_row_template_id => :f4000_p245_id,
    p_region_id => 88449328191587806
  );
dbms_debug_jdwp.disconnect;}'
 where id = 14562627207747006
/
Я использую localhost как имя удалённого хоста, потому что пробросил через SSH свой порт 4000, на котором работает Debug Listener, на порт 50001 сервера с Oracle. Если файерволы Вам позволяют, можете вместо localhost указывать IP машины, на которой работает OSD с удалённой отладкой, тогда порт необходимо указать тот, который выбрали при запуске Remote Debug.


Итак, подготовились к отладке, запустили Remote Debug, зашли на страницу с предпросмотром шаблона отчёта. Началась отладка. За несколько итераций становится ясно, что ошибка возникает при попытке фетчить открытый курсор с запросом отчёта, который ещё не был выполнен. А происходит это, потому что в вызове wwv_render_report3.show не указано значение параметра p_plug_source_type. Исправляем:
update wwv_flow_page_plugs 
   set plug_source = q'{wwv_render_report3.show(
    p_query => '
select 1 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 2 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 3 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 4 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 5 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual union 
select 6 COL1, ''[...]'' COL2, ''[...]'' COL3, sysdate COL4 from dual 
order by 1',
    p_row_template_id => :f4000_p245_id,
    p_region_id => 88449328191587806,
    p_plug_source_type => 'SQL_QUERY'
  );}'
 where id = 14562627207747006
/

Проверяем:


Вот так ищутся и правятся небольшие баги в APEX. Не забывайте делиться своими решениями.

Читать далее

понедельник, 15 октября 2012 г.

APEX 4.2 ушёл в печать!

http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html

PS: Что-то я редко стал сюда что-нибудь добавлять... Потому анонс: в следующих сообщениях расскажу о создании плагинов. Начнём с плагина-региона.
Читать далее

пятница, 22 июня 2012 г.

Oracle APEX 4.2 EA1 ушёл в народ!

На официальной странице APEX появилась приятная новость о доступном Early Adapter (как Oracle именует публичные беты продуктов).
  1. Регистрируйтесь!
  2. Пробуйте!
  3. Пишите предложения и жалобы!
Приятных выходных! ;)
Читать далее

суббота, 12 мая 2012 г.

Oracle APEX: Мелочь, а не хватает...

Казалось бы, не так велик труд: выбрать что-то при редактировании страницы и удалить. Но будь возможность делать это сразу из всплывающего меню! При интенсивном редактировании страницы надоедает вначале заходить в редактировании того же региона, или кнопки, или поля, или... А потом уже DELETE, "Да, я согласен" и обратно к редактированию страницы.

На всякий случай добавил в APEX 4.2 Wish List.
Читать далее

суббота, 10 марта 2012 г.

Oracle APEX Listener: Файл настроек

Это небольшая заметка о файле настроек Oracle APEX Listener (OAL), развёрнутом на GlassFish 3.

По умолчанию OAL создаёт и ищет файл настроек ${java.io.tmpdir}/apex/apex-config.xml, где значение java.io.tmpdir для GlassFish установлено в /tmp. Любые временные директории — не место для хранения файлов настроек, поскольку время от времени их содержимое удаляется.

Чтобы изменить это поведение раз и навсегда, необходимо:
  1. Распаковать файл apex.war. Это обычный zip-архив, проблем с разархивацией возникнуть не должно. Например, разархивируем архив в директорию tmp:
    unzip -d tmp apex.war
  2. Изменить параметр config.dir в файле WEB-INF/web.xml. Найдём в нём следующие строки, устанавливающие значение параметра:
    <!--
      <context-param>
        <param-name>config.dir</param-name>
        <param-value>${java.io.tmpdir}/APEX</param-value>
      </context-param>
    -->
    
    Раскомментируем и заменим значение параметра:
      <context-param>
        <param-name>config.dir</param-name>
        <param-value>${user.dir}</param-value><
      </context-param>
    
    Параметр user.dir для приложения, развёрнутого на GlassFish в домен domain_1, будет иметь значение <Директория GlassFish>/glassfish/domains/domain_1/config. OAL создаст по этому пути поддиректорию apex и разместит файл настроек apex-config.xml в ней.
  3. Создать архив apex.war с изменённым файлом. Перейдём в директорию tmp и соберём архив:
    zip -r apex.war ./*

Всё, архив с приложением готов к установке.

Читать далее

среда, 18 января 2012 г.

Oracle SQL Developer: проблема с горячими клавишами

Предыстория: Не так давно обновил Debian на домашней машине до testing, из-за чего встретился с Gnome 3. Если бы у меня был планшет, наверно, всё было по-другому, однако для настольных ПК это DE недружелюбно. Итогом встречи стал переход на XFCE 4.8, который устроил практически всем. Но...

Проблема: Oracle SQL Developer отказался распознавать текстовые символы с включёнными модификаторами Alt, Ctrl и любыми их комбинациями. То есть, о горячих клавишах можно было забыть.

Причина: Разброд и шатание в настройках клавиатуры.

Ход мыслей: Поначалу я подумал на баги очередного EA, как раз обновил Oracle SQL Developer. Но откат на стабильную версию и удаление настроек (с созданием резервной копии, конечно) ситуацию не изменили. Пришлось внимательнее почитать Сеть. Несколько тем с похожими проблемами натолкнули на мысль, что что-то не так с настройками клавиатуры. И я начал читать про раскладки, X.org, XFCE, udev, evdev и грабли, на которые уже наткнулось прогрессивное человечество.

Развитие X.org server, вначале отказавшегося от хранения настроек в xorg.conf в пользу HAL, а затем — и от HAL в пользу udev, evdev и задания настроек несколькими файлами через /etc/X11/xorg.conf.d, вынудило меня убрать развёвшийся в xorg.conf бардак. Я убрал секции InputDevice для мышки и клавиатуры, убрал ссылки на них в секции ServerLayout. Cоздал файл /etc/X11/xorg.conf.d/99-keyboard.conf, который задаёт для класса устройств типа Keyboard со строкой keyboard в названии драйвер, модель, раскладки и опции:

Section "InputClass"
  Identifier "evdev keyboard catchall"
  MatchIsKeyboard "on"
  MatchDevicePath "/dev/input/event*"
  MatchProduct "keyboard"
  Driver "evdev"
  Option "XkbModel" "logicd"
  Option "XkbRules" "xorg"
  Option "XkbLayout" "us,ru"
  Option "XkbVariant" ",winkeys"
  Option "XkbOptions" "grp:caps_toggle,compose:rwin,terminate:ctrl_alt_bksp"
EndSection

Также, перезагружая иксы и проглядывая раз за разом /var/log/Xorg.0.log, я удалил не поддерживаемые расширения и модули, ненужные видеорежимы и прочий мусор. В /etc/default/keyboard были внесены те же правила для клавиатуры. Однако setxkbmap -print -verbose 10 показывал совсем не то. Оказалось, что xfce4-xkb-plugin отчего-то переопределяет системные настройки, не смотря на соответствующую опцию. За что и был заменён на xxkb.

Итог: Oracle SQL Developer снова работает с горячими клавишами, в настройке устройств ввода наведён небольшой порядок, место индикатора раскладок занял xxkb.

Читать далее

суббота, 31 декабря 2011 г.

НГ-2012

Желаю в наступающем Новом году счастья, здоровья, достаточно воображения для задумок и достаточно сил для их воплощения!
Читать далее

среда, 12 октября 2011 г.

Oracle: ORA-00600 [16305] + ORA-03113 при открытии БД

Обновил в очередной раз Debian на своей домашней машине, запускаю экземпляр Oracle - и что я вижу? ORA-03113 в консоли + ORA-00600 [16305] в alert.log. Порыскав немного по OTN Forums и MOS и попутно заглядывая в трассу PMON, наткнулся на Doc ID 466056.1. Проверяя кэйс, выполнил ifconfig - а в выводе нет работающего loopback-интерфейса. В общем, для решения проблемы было достаточно его поднять:
sudo ifup lo
И можно смело запускать экземпляр.
Читать далее

Oracle: V$SESSION_LONGOPS и несколько одновременных длинных операций

Для того, чтобы отразить в V$SESSION_LONGOPS состояние нескольких одновременных длительных операций - например, общее выполнение процесса и конкретный большой шаг - нужно сохранять значение параметра slno процедуры DBMS_APPLICATION_INFO.set_session_longops. Используя затем пару значений (rindex,slno), можно менять необходимую строку в V$SESSION_LONGOPS. Вот пример работы с двумя длительными операциями:
declare
  first_row pls_integer := dbms_application_info.set_session_longops_nohint;
  second_row pls_integer := dbms_application_info.set_session_longops_nohint;
  slno1 pls_integer;
  slno2 pls_integer;
begin
  dbms_application_info.set_session_longops(rindex => first_row
                                            ,slno => slno1
                                            ,op_name => '1_op'
                                            ,sofar => 1
                                            ,totalwork => 2
                                            ,units => 'step'
                                           );
  dbms_application_info.set_session_longops(rindex => second_row
                                            ,slno => slno2
                                            ,op_name => '2_op'
                                            ,sofar => 1
                                            ,totalwork => 1
                                            ,units => 'step'
                                           );
  dbms_application_info.set_session_longops(rindex => first_row
                                            ,slno => slno1
                                            ,op_name => '1_op'
                                            ,sofar => 2
                                            ,totalwork => 2
                                            ,units => 'step'
                                           );
 
end;
/

select MESSAGE from v$session_longops where (sid,serial#) =
(select sid,serial# from v$session where audsid = USERENV('SESSIONID'));
Тема на SQL.RU: set_session_longops Можно ли вернуться к предидущей строке?
Читать далее