powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопросы по package/procedure
19 сообщений из 44, страница 2 из 2
Вопросы по package/procedure
    #39895455
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
Он нужен прежде всего для логов и информационных сообщений скриптов, то есть пользователем форматтера будет различная автоматизация, которую обслуживают/настраивают админы ИС.
Серверный код не должен зависеть от клиентских nls-настроек.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895457
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
А если он вручную приводит значения с потерей точности, то он видимо знает, что делает, и будет задавать строку формата с учетом своих действий.
Если "пользователь" форматирует значения вручную, для конкатенации результатов такого форматирования ему будет удобнее пользоваться стандартными средствами, а не изучать поведение твоей функции.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895565
IMNO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"оффтоп"
Месье Alibek B. пытается принести JS-стайл в Oracle. Фу фу фу
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895601
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
Или я что-то делаю неправильно?

Нашел ошибку у себя, рекурсия работает нормально.

Текущая версия пакета:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
CREATE OR REPLACE PACKAGE BODY CC_LIBS AS

FUNCTION IIF(expr BOOLEAN, val VARCHAR2, zval VARCHAR2 := NULL) RETURN VARCHAR2 IS
BEGIN
  IF expr THEN RETURN val; ELSE RETURN zval; END IF;
END IIF;
FUNCTION IIF(expr BOOLEAN, val NUMBER, zval NUMBER := NULL) RETURN NUMBER IS
BEGIN
  IF expr THEN RETURN val; ELSE RETURN zval; END IF;
END IIF;
FUNCTION IIF(expr BOOLEAN, val DATE, zval DATE := NULL) RETURN DATE IS
BEGIN
  IF expr THEN RETURN val; ELSE RETURN zval; END IF;
END IIF;

FUNCTION FMT(val VARCHAR2, str VARCHAR2 := NULL) RETURN VARCHAR2 IS
BEGIN
  RETURN val;
END;
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval NUMBER) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval DATE) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2 := NULL) RETURN VARCHAR2 IS
  fmt VARCHAR2(80); nls VARCHAR2(80); i NUMBER := INSTR(str, '|');
BEGIN
  IF (i > 0) THEN
    nls := 'NLS_NUMERIC_CHARACTERS = '''||REPLACE(SUBSTR(str, i+1), '''', '''''')||'''';
    fmt := SUBSTR(str, 1, i-1);
  ELSE
    fmt := str;
  END IF;
  IF (nls IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt, nls);
  ELSIF (fmt IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt);
  ELSE
    RETURN TO_CHAR(val);
  END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2, zval NUMBER) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2, zval DATE) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2 := NULL) RETURN VARCHAR2 IS
  fmt VARCHAR2(80); nls VARCHAR2(80); i NUMBER := INSTR(str, '|');
BEGIN
  IF (i > 0) THEN
    nls := 'NLS_DATE_LANGUAGE = '||REPLACE(SUBSTR(str, i+1), '''', '''''');
    fmt := SUBSTR(str, 1, i-1);
  ELSE
    fmt := str;
  END IF;
  IF (nls IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt, nls);
  ELSIF (fmt IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt);
  ELSE
    RETURN TO_CHAR(val);
  END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2, zval NUMBER) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2, zval DATE) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;

/* ---------------------------------------------------------------------------
  FORMAT (<format string> [, argument list...])
  Форматирование строки в соответствии с шаблоном и передаваемыми данными
  Шаблон обрамляется фигурными или прямоугольными скобками ({} или []).
  В фигурные скобки заключается обычный шаблон.
  В прямоугольные скобки заключается условный шаблон - если в нем отсутствуют 
  значения (равны NULL), то весь шаблон игнорируется (заменяется пустой 
  строкой). Парность скобок не учитывается, тип шаблона определяется по 
  открывающей скобке.
  Символ \ экранирует любой следующий символ. Например \[ используется, чтобы 
  использовать в шаблоне литеральный символ [.
  В шаблоне может быть либо значение, либо вложенный шаблон. Значения всегда 
  предваряются символом $.
  Тип данных значения определяется по содержанию и по формату данных.
  Формат шаблона: "$" index [ "|" format [ "|" nls ] ] [ "@" null ]
  index - порядковый номер аргумента (от 1 до 9) или * (следующий аргумент).
  format - строка формата, передается в to_char() без изменений.
  nls - строка локализации, передается в to_char в зависимости от типа.
  null - используется при пустом значении аргумента
  Примеры:

    Индекс: {$1|FM000000}, город {$2@-}
    Индекс: 012345, город Москва
    Индекс: , город -

    [Трек #{$*|FM00}. ][Альбом '{$*|YYYY} / ]{[{$*} - ]{$*@unknown}}.mp3
    Трек #01. Beatles - Yesterday.mp3
    Альбом '2000 / unknown.mp3

----------------------------------------------------------------------------*/

FUNCTION FORMAT(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) RETURN VARCHAR2 IS

  TKNE CONSTANT CHAR := '\';
  TKNV CONSTANT CHAR := '$';
  TKNO CONSTANT VARCHAR2(10) := '[{\';
  TKNC CONSTANT VARCHAR2(10) := ']}[{\';

  argIndex INT := 0;
  tagPos INT := 1; tagOpen INT; tagClose INT; tagOpt INT;
  ss VARCHAR2(2000); tag VARCHAR2(2000); res VARCHAR2(2000);

  FUNCTION ARG(i INT := 0) RETURN VARCHAR2 IS
  BEGIN
    IF    (i=0) THEN argIndex := argIndex+1; RETURN ARG(argIndex);
    ELSIF (i=1) THEN argIndex := 1; RETURN s1;
    ELSIF (i=2) THEN argIndex := 2; RETURN s2;
    ELSIF (i=3) THEN argIndex := 3; RETURN s3;
    ELSIF (i=4) THEN argIndex := 4; RETURN s4;
    ELSIF (i=5) THEN argIndex := 5; RETURN s5;
    ELSIF (i=6) THEN argIndex := 6; RETURN s6;
    ELSIF (i=7) THEN argIndex := 7; RETURN s7;
    ELSIF (i=8) THEN argIndex := 8; RETURN s8;
    ELSIF (i=9) THEN argIndex := 9; RETURN s9;
    END IF;
  END;

  PROCEDURE SCAN(str VARCHAR2, fmt VARCHAR2, val OUT NUMBER) IS
  BEGIN
    val := NULL;
  END;
  PROCEDURE SCAN(str VARCHAR2, fmt VARCHAR2, val OUT DATE) IS
  BEGIN
    val := NULL;
  END;

  FUNCTION FIND(chars VARCHAR2, pos INT := 1, len INT := 9999) RETURN VARCHAR2 IS
    c INT; n INT := LENGTH(chars); p INT; i INT;
  BEGIN
    FOR c IN 1..n LOOP
      i := INSTR(str, SUBSTR(chars,c,1), pos);
      IF (i > 0 and i <= pos+len) THEN
        IF (p IS NULL OR i < p) THEN
          p := i;
        END IF;
      END IF;
    END LOOP;
    IF (p IS NULL) THEN RETURN 0; ELSE RETURN p; END IF;
  END;

  FUNCTION PAIR(pos INT) RETURN INT IS
    ch CHAR; n INT := LENGTH(str); p INT := pos + 1; i INT; l INT := 1;
  BEGIN
    LOOP
      i := FIND(TKNC, p);
      EXIT WHEN i = 0;
      ch := SUBSTR(str, i, 1);
      IF (ch = TKNE) THEN
        p := i + 2;
      ELSE
        p := i + 1;
        IF (INSTR(TKNO, ch) > 0) THEN
          l := l + 1;
        ELSE
          l := l - 1;
          EXIT WHEN l = 0;
        END IF;
      END IF;
    END LOOP;
    IF (i = 0) THEN i := n + 1; END IF;
    RETURN i;
  END;

  FUNCTION PARSE(expr VARCHAR2) RETURN VARCHAR2 IS
    val VARCHAR2(200); fmt VARCHAR2(200); zval VARCHAR2(200);
    pf INT; pz INT; pi INT; vn NUMBER; vd DATE;
  BEGIN
    IF (expr IS NULL) THEN RETURN NULL; END IF;
    IF (SUBSTR(expr, 1, 1) != TKNV) THEN RETURN NULL; END IF;
    pz := INSTR(expr, '@');
    IF (pz = 0) THEN
      val := SUBSTR(expr, 2);
    ELSE
      val := SUBSTR(expr, 2, pz-2);
      zval := SUBSTR(expr, pz+1);
    END IF;
    pf := INSTR(val, '|');
    IF (pf > 0) THEN
      fmt := SUBSTR(val, pf+1);
      val := SUBSTR(val, 1, pf-1);
    END IF;
    IF (val = '*') THEN
      pi := 0;
    ELSE
      pi := TO_NUMBER(val);
    END IF;
    val := ARG(pi);
    SCAN(val, fmt, vd);
    SCAN(val, fmt, vn);
    fmt := 'YYYY-MM-DD';
    IF    (vd IS NOT NULL) THEN val := CC_LIBS.FMT(vd, fmt, zval);
    ELSIF (vn IS NOT NULL) THEN val := CC_LIBS.FMT(vn, fmt, zval);
    ELSE                        val := CC_LIBS.FMT(val, fmt, zval);
    END IF;
    RETURN val;
  END;

BEGIN
  res := '';
  LOOP
    tagOpt := NULL;
    tagOpen := FIND(TKNO, tagPos);
    EXIT WHEN tagOpen = 0;
    IF (tagOpen > tagPos) THEN res := res || SUBSTR(str, tagPos, tagOpen-tagPos); END IF;
    IF (SUBSTR(str, tagOpen, 1) = TKNE) THEN
      res := res || SUBSTR(str, tagOpen+1, 1);
      tagPos := tagOpen + 2;
    ELSE
      IF (SUBSTR(str, tagOpen, 1) = '[') THEN tagOpt := 0; ELSE tagOpt := -1; END IF;
      tagClose := PAIR(tagOpen);
      tagPos := tagClose + 1;
      ss := SUBSTR(str, tagOpen+1, tagClose-tagOpen-1);
      tag := PARSE(ss);
      IF (tag IS NULL) THEN
        tag := FORMAT(ss, s1,s2,s3,s4,s5,s6,s7,s8,s9);
        IF (tag IS NULL) THEN
          res := res || '@';
        ELSE
          res := res || tag;
        END IF;
      ELSE
        res := res || tag;
      END IF;
    END IF;
  END LOOP;
  res := res || SUBSTR(str, tagPos);
  RETURN res;
END;

PROCEDURE LOG(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
  DBMS_OUTPUT.PUT_LINE(FORMAT(str, s1, s2, s3, s4, s5, s6, s7, s8, s9));
END;

PROCEDURE LOGIF(expr BOOLEAN, str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
  IF expr THEN LOG(str, s1, s2, s3, s4, s5, s6, s7, s8, s9); END IF;
END;

PROCEDURE ERR(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
null;
  RAISE_APPLICATION_ERROR(-20000, FORMAT(str, s1, s2, s3, s4, s5, s6, s7, s8, s9));
END;

PROCEDURE ERRIF(expr BOOLEAN, str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
  IF expr THEN ERR(str, s1, s2, s3, s4, s5, s6, s7, s8, s9); END IF;
END;


END CC_LIBS;



Функция SCAN, которая будет распознавать тип данных, пока еще не готова, поэтому все аргументы обрабатываются как строки.
Плюс условные шаблоны пока не реализованы.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895608
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
Текущая версия пакета:
Для кого этот поток сознания?
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895646
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня были вопросы, мне с ними помогли.
Во-первых, это правила хорошего тона, дать комментарии на советы.
Во-вторых, подобная утилита может кому-нибудь пригодится.
Кому это неинтересно, просто пропустят данную тему.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895667
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
Для коллекции нужно объявить ее тип, затем объявить переменную, затем заполнить коллекцию и только после этого передать в процедуру/функцию. Это получается слишком многословно , по сравнению с util.format или utl_lms.format_message.


когда появилась anydata

я надеялся что со временем доделают неявное преобразование/перегрузку
чтоб дотустимо было

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
declare
 vc varchar2(100) :='a';
 vd date :=sysdate;
 vn number :=0;
 vy sys.anydata;
begin
 vy:=vc;
 vy:=vd;
 vy:=vn;
 vc:=vy;
end;
/



ведь известно ж что надо делать

.....
stax
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895690
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.
подобная утилита может кому-нибудь пригодится.
Недоделаный сырник?
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895701
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
я надеялся что со временем доделают неявное преобразование/перегрузку

Да, я думал, что ANYDATA это псевдотип, который соответствует любому поддерживаемому типу данных.
Без этого применять ANYDATA намного менее удобно.

Elic
Недоделаный сырник?

Эта утилита вполне рабочая, просто пока работает только со строковыми типами данных (точнее все типы данных приводит к строкам). Чуть позже я ее доделаю и выложу окончательную версию. Скелет программы и работа с шаблонами уже готовы и меняться не будут.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895709
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
я надеялся что со временем доделают неявное преобразование/перегрузку
чтоб дотустимо было

В каком формате типы данных отличные от строки должны быть преобразованы в строку и обратно?

PS: классы обертки для примитивных типов и полиморфизм присутствуют в ООП, в pl/sql такие конструкции отсутствуют.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895723
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
я надеялся что со временем доделают неявное преобразование/перегрузку
Создай свой тип с однобуквенным именем и конструкторами/сеттерами на вкус и цвет.
Alibek B.
пока работает только со строковыми типами данных
Твое "пока" не имеет перспектив.
В типичных употреблениях форматера достаточно десяток строковых, десяток числовых параметров, пяток таймстампов, пяток интервалов. Для этого anydata, overload и прочего изобретать не нужно, решается декларацией обычных скалярно-типизованных параметров с default.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895728
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iOracleDev
Stax
я надеялся что со временем доделают неявное преобразование/перегрузку
чтоб дотустимо было

В каком формате типы данных отличные от строки должны быть преобразованы в строку и обратно?

PS: классы обертки для примитивных типов и полиморфизм присутствуют в ООП, в pl/sql такие конструкции отсутствуют.


нет
сохранить согласно типу в правой части
неявно переобразовать/трансформировать в :=sys.anyData.convertVarchar2|date|number...(

зы
также неявно применять :=getXXX
....
stax
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895737
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-
Создай свой тип с однобуквенным именем и конструкторами/сеттерами на вкус и цвет.

Теоретически можно создать тип с набором полей разных примитивных типов, создать конструкторы и сеттеры перегруженные для разных примитивных типов, функции типа isDate, isNumber и т.п., создать перегруженные геттеры-процедуры с out параметром. Только какая от этого практическая польза?
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895742
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

Нельзя проделывать такие фокусы с примитивными типами, с классами можно, pl/sql процедурный язык, конечно нужно было его трансформировать в объектный, лет этак 15 назад, но увы.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895744
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-
Создай свой тип с однобуквенным именем и конструкторами/сеттерами на вкус и цвет.

всеравно придется пользовать конструктор vy:=t.d(sysdate) вместо vy:=sysdate;

хотелка в том чтоб неявное преобразование делал оракля

....
stax
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895754
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iOracleDev
Stax,

Нельзя проделывать такие фокусы с примитивными типами, с классами можно, pl/sql процедурный язык, конечно нужно было его трансформировать в объектный, лет этак 15 назад, но увы.

я не говорю о трансформировании в ООП

говорю что конкретно для ANYDATA добавіть такой "синтаксический" сахар
зачем тогда ANYDATA, если каждый может "создать свой тип с однобуквенным именем и конструкторами/сеттерами на вкус и цвет."

ANYDATA должна иметь чутку своей специфики

напр
в древних версиях кляуза TABLE обязательна, слишал что в новых можно упускать
так и для ANYDATA - разрешить яно не указывать вызов контрукторов

.....
stax
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895762
iOracleDev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

Забили уже давно на pl/sql, не развивается он, только костыли пихают, все хотелки мимо.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39895772
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
хотелка в том чтоб неявное преобразование
Тут немало авторов удивляются ошибке инвалид-нумбер при сравнение текстового поля с числовым значением. Сколько такого работает до поры до времени, хотя могло бы отвалиться еще при статической компиляции.
Stax
"синтаксический" сахар
неявное приведение типов это уже не синтаксический.
...
Рейтинг: 0 / 0
Вопросы по package/procedure
    #39896082
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добавил работу с типами данных number/date.

Декларации

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
CREATE OR REPLACE PACKAGE CC_LIBS AS

FUNCTION IIF(expr BOOLEAN, val VARCHAR2, zval VARCHAR2 := NULL) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(IIF, WNDS, RNDS, WNPS, RNPS);
FUNCTION IIF(expr BOOLEAN, val NUMBER, zval NUMBER := NULL) RETURN NUMBER;
  PRAGMA RESTRICT_REFERENCES(IIF, WNDS, RNDS, WNPS, RNPS);
FUNCTION IIF(expr BOOLEAN, val DATE, zval DATE := NULL) RETURN DATE;
  PRAGMA RESTRICT_REFERENCES(IIF, WNDS, RNDS, WNPS, RNPS);

FUNCTION FMT(val VARCHAR2, str VARCHAR2 := NULL) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval NUMBER) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval DATE) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val NUMBER, str VARCHAR2 := NULL) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val NUMBER, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val NUMBER, str VARCHAR2, zval NUMBER) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val NUMBER, str VARCHAR2, zval DATE) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val DATE, str VARCHAR2 := NULL) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val DATE, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val DATE, str VARCHAR2, zval NUMBER) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);
FUNCTION FMT(val DATE, str VARCHAR2, zval DATE) RETURN VARCHAR2;
  PRAGMA RESTRICT_REFERENCES(FMT, WNDS, RNDS, WNPS, RNPS);

FUNCTION FORMAT(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) RETURN VARCHAR2;

PROCEDURE LOG(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL);
PROCEDURE LOGIF(expr BOOLEAN, str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL);

PROCEDURE ERR(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL);
PROCEDURE ERRIF(expr BOOLEAN, str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL);

END CC_LIBS;




Тело

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
CREATE OR REPLACE PACKAGE BODY CC_LIBS AS

FUNCTION IIF(expr BOOLEAN, val VARCHAR2, zval VARCHAR2 := NULL) RETURN VARCHAR2 IS
BEGIN
  IF expr THEN RETURN val; ELSE RETURN zval; END IF;
END IIF;
FUNCTION IIF(expr BOOLEAN, val NUMBER, zval NUMBER := NULL) RETURN NUMBER IS
BEGIN
  IF expr THEN RETURN val; ELSE RETURN zval; END IF;
END IIF;
FUNCTION IIF(expr BOOLEAN, val DATE, zval DATE := NULL) RETURN DATE IS
BEGIN
  IF expr THEN RETURN val; ELSE RETURN zval; END IF;
END IIF;

FUNCTION FMT(val VARCHAR2, str VARCHAR2 := NULL) RETURN VARCHAR2 IS
BEGIN
  RETURN val;
END;
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval NUMBER) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val VARCHAR2, str VARCHAR2, zval DATE) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2 := NULL) RETURN VARCHAR2 IS
  fmt VARCHAR2(80); nls VARCHAR2(80); i NUMBER := INSTR(str, '|');
BEGIN
  IF (i > 0) THEN
    nls := 'NLS_NUMERIC_CHARACTERS = '''||REPLACE(SUBSTR(str, i+1), '''', '''''')||'''';
    fmt := SUBSTR(str, 1, i-1);
  ELSE
    fmt := str;
  END IF;
  IF (nls IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt, nls);
  ELSIF (fmt IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt);
  ELSE
    RETURN TO_CHAR(val);
  END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2, zval NUMBER) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val NUMBER, str VARCHAR2, zval DATE) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2 := NULL) RETURN VARCHAR2 IS
  fmt VARCHAR2(80); nls VARCHAR2(80); i NUMBER := INSTR(str, '|');
BEGIN
  IF (i > 0) THEN
    nls := 'NLS_DATE_LANGUAGE = '||REPLACE(SUBSTR(str, i+1), '''', '''''');
    fmt := SUBSTR(str, 1, i-1);
  ELSE
    fmt := str;
  END IF;
  IF (nls IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt, nls);
  ELSIF (fmt IS NOT NULL) THEN
    RETURN TO_CHAR(val, fmt);
  ELSE
    RETURN TO_CHAR(val);
  END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2, zval VARCHAR2) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2, zval NUMBER) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;
FUNCTION FMT(val DATE, str VARCHAR2, zval DATE) RETURN VARCHAR2 IS
BEGIN
  IF (val IS NOT NULL) THEN RETURN FMT(val, str); ELSE RETURN FMT(zval, str); END IF;
END;

/* ---------------------------------------------------------------------------
  FORMAT (<format string> [, argument list...])
  Форматирование строки в соответствии с шаблоном и передаваемыми данными
  Шаблон обрамляется фигурными или прямоугольными скобками ({} или []).
  В фигурные скобки заключается обычный шаблон.
  В прямоугольные скобки заключается условный шаблон - если в нем отсутствуют 
  значения (равны NULL), то весь шаблон игнорируется (заменяется пустой 
  строкой). Парность скобок не учитывается, тип шаблона определяется по 
  открывающей скобке.
  Символ \ экранирует любой следующий символ. Например \[ используется, чтобы 
  использовать в шаблоне литеральный символ [.
  В шаблоне может быть либо значение, либо вложенный шаблон. Значения всегда 
  предваряются символом $.
  Тип данных значения определяется по содержанию и по формату данных.
  Формат шаблона: "$" index [ "|" format [ "|" nls ] ] [ "@" null ]
  index - порядковый номер аргумента (от 1 до 9) или * (следующий аргумент).
  format - строка формата, передается в to_char() без изменений.
  nls - строка локализации, передается в to_char в зависимости от типа.
  null - используется при пустом значении аргумента
  Примеры:

    Индекс: {$1|FM000000}, город {$2@-}
    Индекс: 012345, город Москва
    Индекс: , город -

    [Трек #{$*|FM00}. ][Альбом '{$*|YYYY} / ]{[{$*} - ]{$*@unknown}}.mp3
    Трек #01. Beatles - Yesterday.mp3
    Альбом '2000 / unknown.mp3

----------------------------------------------------------------------------*/

FUNCTION FORMAT(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) RETURN VARCHAR2 IS

  TKNE CONSTANT CHAR := '\';
  TKNV CONSTANT CHAR := '$';
  TKNO CONSTANT VARCHAR2(10) := '[{\';
  TKNC CONSTANT VARCHAR2(10) := ']}[{\';

  argIndex INT := 0;
  tagPos INT := 1; tagOpen INT; tagClose INT; tagOpt INT;
  ss VARCHAR2(2000); tag VARCHAR2(2000); res VARCHAR2(2000);

  FUNCTION ARG(i INT := 0) RETURN VARCHAR2 IS
  BEGIN
    IF    (i=0) THEN argIndex := argIndex+1; RETURN ARG(argIndex);
    ELSIF (i=1) THEN argIndex := 1; RETURN s1;
    ELSIF (i=2) THEN argIndex := 2; RETURN s2;
    ELSIF (i=3) THEN argIndex := 3; RETURN s3;
    ELSIF (i=4) THEN argIndex := 4; RETURN s4;
    ELSIF (i=5) THEN argIndex := 5; RETURN s5;
    ELSIF (i=6) THEN argIndex := 6; RETURN s6;
    ELSIF (i=7) THEN argIndex := 7; RETURN s7;
    ELSIF (i=8) THEN argIndex := 8; RETURN s8;
    ELSIF (i=9) THEN argIndex := 9; RETURN s9;
    END IF;
  END;

  FUNCTION SCAN(str VARCHAR2, fmt VARCHAR2, val OUT NUMBER) RETURN BOOLEAN IS
    flag BOOLEAN := FALSE; v VARCHAR2(200); f VARCHAR2(200) := UPPER(fmt); i INT := INSTR(fmt, '|'); nls VARCHAR2(80);
  BEGIN
    IF (i > 0) THEN
      f := SUBSTR(f, 1, i-1);
    END IF;
    val := NULL;
    IF (f IS NOT NULL) THEN
      IF    (SUBSTR(f,1,2) = 'FM') THEN
        f := 'FM';
      ELSIF (SUBSTR(f,1,2) = 'TM') THEN
        f := 'RN';
      ELSIF (SUBSTR(f,1,2) = 'RM') THEN
        f := 'RN';
      ELSIF (INSTR(f,'X') > 0) THEN
        f := 'X';
      ELSIF (INSTR(f,'0') > 0) THEN
        f := '0';
      ELSIF (INSTR(f,'9') > 0) THEN
        f := '9';
      ELSE
        f := NULL;
      END IF;
      IF (f IS NOT NULL) THEN flag := TRUE; END IF;
    END IF;
    IF (str IS NOT NULL) THEN
      IF (REGEXP_LIKE(str, '^\d+$')) THEN
        flag := TRUE; val := TO_NUMBER(str);
      ELSIF (REGEXP_LIKE(str, '^\d*\.\d*$')) THEN
        flag := TRUE; val := TO_NUMBER(str, '999999999999999999999999999999D99999999999999999999', 'NLS_NUMERIC_CHARACTERS = ''. ''');
      ELSIF (REGEXP_LIKE(str, '^\d*\,\d*$')) THEN
        flag := TRUE; val := TO_NUMBER(str, '999999999999999999999999999999D99999999999999999999', 'NLS_NUMERIC_CHARACTERS = '', ''');
      ELSE
        IF (v IS NULL) THEN
          BEGIN
            v := CAST(str AS NUMBER);
            flag := TRUE; val := v;
          EXCEPTION WHEN OTHERS THEN flag := FALSE;
          END;
        END IF;
        IF (v IS NULL) THEN
          BEGIN
            IF (fmt IS NULL) THEN
              v := TO_NUMBER(str);
            ELSE
              v := TO_NUMBER(str, fmt);
            END IF;
            flag := TRUE; val := v;
          EXCEPTION WHEN OTHERS THEN flag := FALSE;
          END;
        END IF;
      END IF;
    END IF;
    RETURN flag;
  END;
  FUNCTION SCAN(str VARCHAR2, fmt VARCHAR2, val OUT DATE) RETURN BOOLEAN IS
    flag BOOLEAN := FALSE; v VARCHAR2(200); f VARCHAR2(200) := UPPER(fmt); i INT := INSTR(fmt, '|'); nls VARCHAR2(80);
  BEGIN
    IF (i > 0) THEN
      nls := 'NLS_DATE_LANGUAGE = '||REPLACE(SUBSTR(fmt, i+1), '''', '''''');
      f := SUBSTR(f, 1, i-1);
    END IF;
    val := NULL;
    IF (f IS NOT NULL) THEN
      IF    (SUBSTR(f,1,2) = 'FX') THEN
        f := 'FX';
      ELSIF (INSTR(f,'SS') > 0) THEN
        f := 'SS';
      ELSIF (INSTR(f,'MI') > 0) THEN
        f := 'MI';
      ELSIF (INSTR(f,'HH') > 0) THEN
        f := 'HH';
      ELSIF (INSTR(f,'TZ') > 0) THEN
        f := 'TZ';
      ELSIF (INSTR(f,'DD') > 0) THEN
        f := 'DD';
      ELSIF (INSTR(f,'DAY') > 0) THEN
        f := 'DAY';
      ELSIF (INSTR(f,'MM') > 0) THEN
        f := 'MM';
      ELSIF (INSTR(f,'MON') > 0) THEN
        f := 'MON';
      ELSIF (INSTR(f,'YY') > 0) THEN
        f := 'YY';
      ELSIF (INSTR(f,'YEAR') > 0) THEN
        f := 'YEAR';
      ELSIF (INSTR(f,'RM') > 0) THEN
        f := 'RM';
      ELSE
        f := NULL;
      END IF;
      IF (f IS NOT NULL) THEN flag := TRUE; END IF;
    END IF;
    IF (str IS NOT NULL) THEN
      IF (str = 'sysdate') THEN
        f := NULL; v := sysdate; val := v;
      ELSIF (REGEXP_LIKE(str, '^\s*d{4}[-/.]\d{1,2}[-/.]\d{1,2}.+?\d{1,2}[:-]\d{1,2}[:-]\d{1,2}\s*$')) THEN
        f := 'YYYY-MM-DD HH24:MI:SS';
      ELSIF (REGEXP_LIKE(str, '^\s*\d{4}[-/.]\d{1,2}[-/.]\d{1,2}\s*$')) THEN
        f := 'YYYY-MM-DD';
      ELSIF (REGEXP_LIKE(str, '^\s*\d{1,2}[:-]\d{1,2}[:-]\d{1,2}\s*$')) THEN
        f := 'HH24:MI:SS';
      ELSIF (REGEXP_LIKE(str, '^\s*d{4}[-/. ]\w+[-/. ]\d{1,2}')) THEN
        f := 'YYYY-MON-DD HH24:MI:SS';
      ELSIF (REGEXP_LIKE(str, '^\s*\w+[-/. ]d{1,2}[-/. ]\d{4}')) THEN
        f := 'MON/DD/YYYY HH24:MI:SS';
      ELSE
        f := NULL;
      END IF;
      IF (f IS NOT NULL) THEN
        BEGIN
          IF (nls IS NULL) THEN
            v := TO_DATE(str, f);
          ELSE
            v := TO_DATE(str, f, nls);
          END IF;
          flag := TRUE; val := v;
        EXCEPTION WHEN OTHERS THEN flag := FALSE;
        END;
      END IF;
      IF (v IS NULL AND fmt IS NOT NULL) THEN
        BEGIN
          IF (nls IS NULL) THEN
            v := TO_DATE(str, fmt);
          ELSE
            v := TO_DATE(str, fmt, nls);
          END IF;
          flag := TRUE; val := v;
        EXCEPTION WHEN OTHERS THEN NULL;
        END;
      END IF;
      IF (v IS NULL) THEN
        BEGIN
          v := TO_DATE(str);
          flag := TRUE; val := v;
        EXCEPTION WHEN OTHERS THEN flag := FALSE;
        END;
      END IF;
    END IF;
    RETURN flag;
  END;

  FUNCTION FIND(chars VARCHAR2, pos INT := 1, len INT := 9999) RETURN VARCHAR2 IS
    c INT; n INT := LENGTH(chars); p INT; i INT;
  BEGIN
    FOR c IN 1..n LOOP
      i := INSTR(str, SUBSTR(chars,c,1), pos);
      IF (i > 0 and i <= pos+len) THEN
        IF (p IS NULL OR i < p) THEN
          p := i;
        END IF;
      END IF;
    END LOOP;
    IF (p IS NULL) THEN RETURN 0; ELSE RETURN p; END IF;
  END;

  FUNCTION PAIR(pos INT) RETURN INT IS
    ch CHAR; n INT := LENGTH(str); p INT := pos + 1; i INT; l INT := 1;
  BEGIN
    LOOP
      i := FIND(TKNC, p);
      EXIT WHEN i = 0;
      ch := SUBSTR(str, i, 1);
      IF (ch = TKNE) THEN
        p := i + 2;
      ELSE
        p := i + 1;
        IF (INSTR(TKNO, ch) > 0) THEN
          l := l + 1;
        ELSE
          l := l - 1;
          EXIT WHEN l = 0;
        END IF;
      END IF;
    END LOOP;
    IF (i = 0) THEN i := n + 1; END IF;
    RETURN i;
  END;

  FUNCTION PARSE(expr VARCHAR2) RETURN VARCHAR2 IS
    val VARCHAR2(200); fmt VARCHAR2(200); zval VARCHAR2(200);
    pf INT; pz INT; pi INT; vn NUMBER; vd DATE;
  BEGIN
    IF (expr IS NULL) THEN RETURN NULL; END IF;
    IF (SUBSTR(expr, 1, 1) != TKNV) THEN RETURN NULL; END IF;
    pz := INSTR(expr, '@');
    IF (pz = 0) THEN
      val := SUBSTR(expr, 2);
    ELSE
      val := SUBSTR(expr, 2, pz-2);
      zval := SUBSTR(expr, pz+1);
    END IF;
    pf := INSTR(val, '|');
    IF (pf > 0) THEN
      fmt := SUBSTR(val, pf+1);
      val := SUBSTR(val, 1, pf-1);
    END IF;
    IF (val = '*') THEN
      pi := 0;
    ELSE
      pi := TO_NUMBER(val);
    END IF;
    val := ARG(pi);
    IF    SCAN(val, fmt, vd) THEN
      val := CC_LIBS.FMT(vd, fmt, zval);
    ELSIF SCAN(val, fmt, vn) THEN
      val := CC_LIBS.FMT(vn, fmt, zval);
    ELSE
      val := CC_LIBS.FMT(val, fmt, zval);
    END IF;
    RETURN val;
  END;

BEGIN
  res := '';
  LOOP
    tagOpt := NULL;
    tagOpen := FIND(TKNO, tagPos);
    EXIT WHEN tagOpen = 0;
    IF (tagOpen > tagPos) THEN res := res || SUBSTR(str, tagPos, tagOpen-tagPos); END IF;
    IF (SUBSTR(str, tagOpen, 1) = TKNE) THEN
      res := res || SUBSTR(str, tagOpen+1, 1);
      tagPos := tagOpen + 2;
    ELSE
      IF (SUBSTR(str, tagOpen, 1) = '[') THEN tagOpt := 0; ELSE tagOpt := -1; END IF;
      tagClose := PAIR(tagOpen);
      tagPos := tagClose + 1;
      ss := SUBSTR(str, tagOpen+1, tagClose-tagOpen-1);
      tag := PARSE(ss);
      IF (tag IS NULL) THEN
        tag := FORMAT(ss, s1,s2,s3,s4,s5,s6,s7,s8,s9);
        IF (tag IS NULL) THEN
          res := res || '@';
        ELSE
          res := res || tag;
        END IF;
      ELSE
        res := res || tag;
      END IF;
    END IF;
  END LOOP;
  res := res || SUBSTR(str, tagPos);
  RETURN res;
END;

PROCEDURE LOG(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
  DBMS_OUTPUT.PUT_LINE(FORMAT(str, s1, s2, s3, s4, s5, s6, s7, s8, s9));
END;

PROCEDURE LOGIF(expr BOOLEAN, str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
  IF expr THEN LOG(str, s1, s2, s3, s4, s5, s6, s7, s8, s9); END IF;
END;

PROCEDURE ERR(str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
null;
  RAISE_APPLICATION_ERROR(-20000, FORMAT(str, s1, s2, s3, s4, s5, s6, s7, s8, s9));
END;

PROCEDURE ERRIF(expr BOOLEAN, str VARCHAR2, s1 VARCHAR2 := NULL, s2 VARCHAR2 := NULL, s3 VARCHAR2 := NULL, s4 VARCHAR2 := NULL, s5 VARCHAR2 := NULL, s6 VARCHAR2 := NULL, s7 VARCHAR2 := NULL, s8 VARCHAR2 := NULL, s9 VARCHAR2 := NULL) IS
BEGIN
  IF expr THEN ERR(str, s1, s2, s3, s4, s5, s6, s7, s8, s9); END IF;
END;


END CC_LIBS;




Версия еще не окончательная, не сделаны условные шаблоны (возвращать пустую строку, если внутри шаблона отсутствуют значения), пока не придумал, как это сделать. Через пару дней доделаю.

Пример:
Код: plaintext
1.
2.
3.
4.
5.
6.
select cc_libs.format('#{$1|FM0000}. Цена {$2|FM9G999G990D00|.''@<нет>}', 1, 1234567.345) s from dual;
/

S
-
#0001. Цена 1'234'567.35
...
Рейтинг: 0 / 0
19 сообщений из 44, страница 2 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопросы по package/procedure
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]