После реализации nodejs приложения возникла задача его демонизации. Один из способов - использование модуля, разработанного nodejitsu - forever. Для установки данного модуля воспользуйтесь командой (Ubuntu Server):
sudo npm -g install forever
После этого можно запустить выполнение вашего nodejs приложения с помощью forever в виде самостоятельного сервиса:
forever start /path/to/directory/containing_your_app/your_app_name.js
forever будет отслеживать за падениями приложения и пытаться его поднять. В случае же рестарта системы, запуска вашего сервиса не произойдет. Здесь нужно реализовать автозагрузку на уровне системы. Создайте скрипт запуска в директории /etc/init.d. Ниже приведен пример скрипта автозапуска /etc/init.d/your_app_name:
#!/bin/bash
#
# description: your_app_name (node) service
#
# use commands:
# service your_app_name <command (start|stop|status|restart)>
SERVICE_NAME=your_app_name
SOURCE_DIR=/path/to/directory/containing_your_app
SOURCE_NAME=your_app_name.js
SOURCE_PATH=$SOURCE_DIR/$SOURCE_NAME
LOG_DIR=$SOURCE_DIR/forever
USER=tester
pidfile=/home/$USER/.forever/pids/$SERVICE_NAME.pid
logfile=$LOG_DIR/forever.log
outfile=$LOG_DIR/output.log
errfile=$LOG_DIR/error.log
case "$1" in
start)
forever start -l $logfile -o $outfile -e $errfile --pidFile $pidfile -a $SOURCE_PATH
;;
stop)
forever stop --pidFile $pidfile $SOURCE_PATH
;;
status)
forever list
;;
restart)
forever restart -l $logfile -o $outfile -e $errfile --pidFile $pidfile -a $SOURCE_PATH
;;
*)
echo "Usage: $SERVICE_NAME {start|stop|status|restart}"
exit 1
;;
esac
exit 0
Далее выдайте права:
sudo chmod 755 /etc/init.d/your_app_name
и пропишите его в автозагрузку:
sudo update-rc.d your_app_name defaults
Oracle. ORA-21561: OID generation failed
После установки клиента при попытке коннекта выбрасывается следующая ошибка
Для устранения необходимо добавить имя хоста в файл hosts:
$ hostname
$ nano /etc/hosts
> 127.0.0.1 localhost hostname
PLSQL. JSON validator (string validation)
Как известно, JSON формат представляет собой альтернативу XML формату. В настоящее время данный формат получил довольно широкое распространение. Так же и Oracle не отстает от времени и в версии 12.1.0.2 была добавлена нативная поддержка JSON формата. Если Вы работаете на более поздних версиях, то можно добавить собственные реализации для поддержки формата. Есть уже и готовые решения, например можно воспользоваться следующим ресурсом - https://github.com/pljson/pljson.
В моем же случае все немного проще. На стороне сервера по триггеру запускался обработчик, который формировал данные в строковом виде в JSON формате и после отправлял POST запросом на определенный ресурс. Перед отправкой необходимо было убедиться в валидности JSON формата. Так возникла потребность в организации такого рода JSON валидатора. За основу был взят JSON парсер, написанный Дугласом Крокфордом на javascript, с которым можно ознакомиться по ссылке - https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js. Данный парсер предоставляет альтернативу встроенному парсеру JSON.parse в случае отсутствия поддержки оного в Вашем браузере. Ниже представлена реализация тела пакета данного валидатора. В спецификации внешний доступ предоставлен трем методам:
function unsafety_validate(source in varchar2) return boolean;
function safety_validate(source in varchar2) return boolean;
function safety_validate(source in varchar2, errmsg in out varchar2) return boolean;
Префиксы - safety и unsafety - указывают на возможность генерирования возникающих в ходе валидации исключений. С полным описанием пакета можно ознакомиться по ссылке - https://github.com/mozg1984/PL-JSON-VALIDATOR.
create or replace package body json_validator is
/* @private
* type for instantiate keys storages
*/
type array_t is table of varchar2(1000);
atCh integer; -- the index of the current character
ch char; -- the current character
text varchar2(32767);
/* @private
* call error when something is wrong
*/
procedure error(m in varchar2 default '')
is
errmsg varchar2(32767);
begin
errmsg := 'name: SyntaxError, ';
errmsg := errmsg || 'message: ' || m || ', ';
errmsg := errmsg || 'at: ' || atCh || ', ';
errmsg := errmsg || 'text: ' || text;
raise_application_error(-20000, errmsg);
end;
/* @private
* escape sequence
*/
function escapee(ch in char default '') return varchar2
is
begin
case ch
when '"' then return '"';
when '\' then return '\';
when '/' then return '/';
when 'b' then return '\b';
when 'f' then return '\f';
when 'n' then return '\n';
when 'r' then return '\r';
when 't' then return '\t';
else return null;
end case;
end;
/* @private
* add key to keys storage
*/
procedure add_key(p_array in out nocopy array_t, p_key in varchar2)
is
begin
p_array.extend();
p_array(p_array.count()) := p_key;
exception
when collection_is_null then
p_array := array_t(p_key);
end;
/* @private
* check duplicate keys in keys storage
*/
function has_key(p_array in out nocopy array_t, p_key in varchar2) return boolean
is
is_equal boolean := false;
begin
for i in p_array.first..p_array.last loop
if p_array(i) = p_key then
is_equal := true;
end if;
end loop;
return is_equal;
exception
when collection_is_null then
return is_equal;
end;
/* @private
* get char from string by index position
*/
function charAt(str in varchar2, pos in integer) return char
is
begin
return substr(str, pos, 1);
end;
/* @private
* check if given number
*/
function isNumber(num in varchar2) return boolean
is
begin
case regexp_like(num, '^\d*\.?\d+$')
when true then
return true;
else
return false;
end case;
end;
/* @private
* check if given character
*/
function exist(ch in varchar2 default '') return boolean
is
begin
return ch is not null;
end;
/* @private
* convert hex number (character) to decimal number
*/
function hex2dec(ch in char) return number
is
begin
return to_number(ch, 'x');
exception
when value_error then
return null;
end;
/* @private
* convert hex code to unicode character
*/
function getUnicodeChar(hexcode in varchar2) return varchar2
is
begin
return trim(unistr('\' || hexcode || ' '));
exception
when others then
return '';
end;
/* @private
* get the next character
*/
function nextChar(c in char default '') return char
is
begin
-- if a c parameter is provided, verify that it matches the current character
if (exist(c) and c != ch) then
error('Expected ''' || c || ''' instead of ''' || ch || '''');
end if;
-- when there are no more characters, return the empty string
ch := charAt(text, atCh);
atCh := atCh + 1;
return ch;
end;
/* @private
* move current char to next
*/
procedure nextChar(c in char default '')
is
begin
-- if a c parameter is provided, verify that it matches the current character
if (exist(c) and c != ch) then
error('Expected ''' || c || ''' instead of ''' || ch || '''');
end if;
ch := charAt(text, atCh);
atCh := atCh + 1;
end;
/* @private
* forward declaration of common validate function
*/
function validate return boolean;
/* @private
* validate a number value
*/
function validateNumber return boolean
is
l_number varchar2(32767) := '';
begin
if (ch = '-') then
l_number := '-';
nextChar('-');
end if;
while (ch >= '0' and ch <= '9') loop
l_number := l_number || ch;
nextChar();
end loop;
if (ch = '.') then
l_number := l_number || '.';
while (exist(nextChar()) and ch >= '0' and ch <= '9') loop
l_number := l_number || ch;
end loop;
end if;
if (ch = 'e' or ch = 'E') then
l_number := l_number || ch;
nextChar();
if (ch = '-' or ch = '+') then
l_number := l_number || ch;
nextChar();
end if;
while (ch >= '0' and ch <= '9') loop
l_number := l_number || ch;
nextChar();
end loop;
end if;
if (not(isNumber(l_number))) then
error('Bad number');
else
return true;
end if;
end;
/* @private
* validate a string value
*/
function validateString return boolean
is
decnum number;
begin
-- when parsing for string values, we must look for " and \ characters
if (ch = '"') then
while (exist(nextChar())) loop
if (ch = '"') then
nextChar();
return true;
end if;
if (ch = '\') then
nextChar();
if (ch = 'u') then
for i in 1..4 loop
decnum := hex2dec(nextChar());
if (not isNumber(decnum)) then
error('Malformed Unicode character escape sequence');
end if;
end loop;
elsif (escapee(ch) is not null) then
null;
else
exit;
end if;
end if;
end loop;
end if;
error('Bad string');
end;
/* @private
* get string key value (for checking duplicate keys in object value)
*/
function stringKey return varchar2
is
l_string varchar2(32767) := '';
decnum number;
uffff varchar2(32767);
begin
-- when parsing for string values, we must look for " and \ characters
if (ch = '"') then
while (exist(nextChar())) loop
if (ch = '"') then
nextChar();
return l_string;
end if;
if (ch = '\') then
nextChar();
if (ch = 'u') then
uffff := '';
for i in 1..4 loop
decnum := hex2dec(nextChar());
if (not isNumber(decnum)) then
error('Malformed Unicode character escape sequence');
end if;
uffff := uffff || ch;
end loop;
l_string := l_string || getUnicodeChar(uffff);
elsif (escapee(ch) is not null) then
l_string := l_string || escapee(ch);
else
exit;
end if;
else
l_string := l_string || ch;
end if;
end loop;
end if;
error('Bad string');
end;
/* @private
* skip whitespace
*/
procedure white
is
begin
while (exist(ch) and ch <= ' ') loop
nextChar();
end loop;
end;
/* @private
* validate a word (true, false or null)
*/
function validateWord return boolean
is
begin
case ch
when 't' then
nextChar('t');
nextChar('r');
nextChar('u');
nextChar('e');
return true;
when 'f' then
nextChar('f');
nextChar('a');
nextChar('l');
nextChar('s');
nextChar('e');
return true;
when 'n' then
nextChar('n');
nextChar('u');
nextChar('l');
nextChar('l');
return true;
else
error('Unexpected ''' || ch || '''');
end case;
end;
/* @private
* validate an array value
*/
function validateArray return boolean
is
l_result boolean := true;
begin
if (ch = '[') then
nextChar('[');
white();
if (ch = ']') then
nextChar(']');
return l_result; -- empty array
end if;
while (exist(ch)) loop
l_result := validate();
white();
if (ch = ']') then
nextChar(']');
return l_result;
end if;
nextChar(',');
white();
end loop;
end if;
error('Bad array');
end;
/* @private
* validate an object value
*/
function validateObject return boolean
is
l_result boolean := true;
l_key varchar2(1000);
l_keys array_t;
begin
if (ch = '{') then
nextChar('{');
white();
if (ch = '}') then
nextChar('}');
return l_result; -- empty object
end if;
while (exist(ch)) loop
l_key := stringKey();
white();
nextChar(':');
if (has_key(l_keys, l_key)) then
error('Duplicate key "' || l_key || '"');
end if;
add_key(l_keys, l_key);
l_result := validate();
white();
if (ch = '}') then
nextChar('}');
return l_result;
end if;
nextChar(',');
white();
end loop;
end if;
error('Bad object');
end;
/* @public
* validate a JSON value.
* It could be an object, an array, a string, a number, or a word.
*/
function validate return boolean
is
begin
white();
case ch
when '{' then
return validateObject();
when '[' then
return validateArray();
when '"' then
return validateString();
when '-' then
return validateNumber();
else
return case
when (ch >= '0' and ch <= '9') then validateNumber() else validateWord() end;
end case;
end;
/* @public
* unsafety validate JSON string (throw exception ora-20000)
*/
function unsafety_validate(source in varchar2) return boolean
is
l_result boolean;
begin
text := source;
atCh := 1;
ch := ' ';
l_result := validate();
white();
if (exist(ch)) then
error('Syntax error');
end if;
return l_result;
end;
/* @public
* safety validate JSON string (catch all exceptions)
*/
function safety_validate(source in varchar2) return boolean
is
l_result boolean;
begin
text := source;
atCh := 1;
ch := ' ';
l_result := validate();
white();
if (exist(ch)) then
error('Syntax error');
end if;
return l_result;
exception
when others then
return false;
end;
/* @public
* safety validate JSON string (catch all exceptions with error message)
*/
function safety_validate(source in varchar2,
errmsg in out varchar2) return boolean
is
l_result boolean;
begin
text := source;
atCh := 1;
ch := ' ';
l_result := validate();
white();
if (exist(ch)) then
error('Syntax error');
end if;
return l_result;
exception
when others then
errmsg := sqlerrm;
return false;
end;
begin
-- init
null;
end json_validator;
В моем же случае все немного проще. На стороне сервера по триггеру запускался обработчик, который формировал данные в строковом виде в JSON формате и после отправлял POST запросом на определенный ресурс. Перед отправкой необходимо было убедиться в валидности JSON формата. Так возникла потребность в организации такого рода JSON валидатора. За основу был взят JSON парсер, написанный Дугласом Крокфордом на javascript, с которым можно ознакомиться по ссылке - https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js. Данный парсер предоставляет альтернативу встроенному парсеру JSON.parse в случае отсутствия поддержки оного в Вашем браузере. Ниже представлена реализация тела пакета данного валидатора. В спецификации внешний доступ предоставлен трем методам:
function unsafety_validate(source in varchar2) return boolean;
function safety_validate(source in varchar2) return boolean;
function safety_validate(source in varchar2, errmsg in out varchar2) return boolean;
Префиксы - safety и unsafety - указывают на возможность генерирования возникающих в ходе валидации исключений. С полным описанием пакета можно ознакомиться по ссылке - https://github.com/mozg1984/PL-JSON-VALIDATOR.
create or replace package body json_validator is
/* @private
* type for instantiate keys storages
*/
type array_t is table of varchar2(1000);
atCh integer; -- the index of the current character
ch char; -- the current character
text varchar2(32767);
/* @private
* call error when something is wrong
*/
procedure error(m in varchar2 default '')
is
errmsg varchar2(32767);
begin
errmsg := 'name: SyntaxError, ';
errmsg := errmsg || 'message: ' || m || ', ';
errmsg := errmsg || 'at: ' || atCh || ', ';
errmsg := errmsg || 'text: ' || text;
raise_application_error(-20000, errmsg);
end;
/* @private
* escape sequence
*/
function escapee(ch in char default '') return varchar2
is
begin
case ch
when '"' then return '"';
when '\' then return '\';
when '/' then return '/';
when 'b' then return '\b';
when 'f' then return '\f';
when 'n' then return '\n';
when 'r' then return '\r';
when 't' then return '\t';
else return null;
end case;
end;
/* @private
* add key to keys storage
*/
procedure add_key(p_array in out nocopy array_t, p_key in varchar2)
is
begin
p_array.extend();
p_array(p_array.count()) := p_key;
exception
when collection_is_null then
p_array := array_t(p_key);
end;
/* @private
* check duplicate keys in keys storage
*/
function has_key(p_array in out nocopy array_t, p_key in varchar2) return boolean
is
is_equal boolean := false;
begin
for i in p_array.first..p_array.last loop
if p_array(i) = p_key then
is_equal := true;
end if;
end loop;
return is_equal;
exception
when collection_is_null then
return is_equal;
end;
/* @private
* get char from string by index position
*/
function charAt(str in varchar2, pos in integer) return char
is
begin
return substr(str, pos, 1);
end;
/* @private
* check if given number
*/
function isNumber(num in varchar2) return boolean
is
begin
case regexp_like(num, '^\d*\.?\d+$')
when true then
return true;
else
return false;
end case;
end;
/* @private
* check if given character
*/
function exist(ch in varchar2 default '') return boolean
is
begin
return ch is not null;
end;
/* @private
* convert hex number (character) to decimal number
*/
function hex2dec(ch in char) return number
is
begin
return to_number(ch, 'x');
exception
when value_error then
return null;
end;
/* @private
* convert hex code to unicode character
*/
function getUnicodeChar(hexcode in varchar2) return varchar2
is
begin
return trim(unistr('\' || hexcode || ' '));
exception
when others then
return '';
end;
/* @private
* get the next character
*/
function nextChar(c in char default '') return char
is
begin
-- if a c parameter is provided, verify that it matches the current character
if (exist(c) and c != ch) then
error('Expected ''' || c || ''' instead of ''' || ch || '''');
end if;
-- when there are no more characters, return the empty string
ch := charAt(text, atCh);
atCh := atCh + 1;
return ch;
end;
/* @private
* move current char to next
*/
procedure nextChar(c in char default '')
is
begin
-- if a c parameter is provided, verify that it matches the current character
if (exist(c) and c != ch) then
error('Expected ''' || c || ''' instead of ''' || ch || '''');
end if;
ch := charAt(text, atCh);
atCh := atCh + 1;
end;
/* @private
* forward declaration of common validate function
*/
function validate return boolean;
/* @private
* validate a number value
*/
function validateNumber return boolean
is
l_number varchar2(32767) := '';
begin
if (ch = '-') then
l_number := '-';
nextChar('-');
end if;
while (ch >= '0' and ch <= '9') loop
l_number := l_number || ch;
nextChar();
end loop;
if (ch = '.') then
l_number := l_number || '.';
while (exist(nextChar()) and ch >= '0' and ch <= '9') loop
l_number := l_number || ch;
end loop;
end if;
if (ch = 'e' or ch = 'E') then
l_number := l_number || ch;
nextChar();
if (ch = '-' or ch = '+') then
l_number := l_number || ch;
nextChar();
end if;
while (ch >= '0' and ch <= '9') loop
l_number := l_number || ch;
nextChar();
end loop;
end if;
if (not(isNumber(l_number))) then
error('Bad number');
else
return true;
end if;
end;
/* @private
* validate a string value
*/
function validateString return boolean
is
decnum number;
begin
-- when parsing for string values, we must look for " and \ characters
if (ch = '"') then
while (exist(nextChar())) loop
if (ch = '"') then
nextChar();
return true;
end if;
if (ch = '\') then
nextChar();
if (ch = 'u') then
for i in 1..4 loop
decnum := hex2dec(nextChar());
if (not isNumber(decnum)) then
error('Malformed Unicode character escape sequence');
end if;
end loop;
elsif (escapee(ch) is not null) then
null;
else
exit;
end if;
end if;
end loop;
end if;
error('Bad string');
end;
/* @private
* get string key value (for checking duplicate keys in object value)
*/
function stringKey return varchar2
is
l_string varchar2(32767) := '';
decnum number;
uffff varchar2(32767);
begin
-- when parsing for string values, we must look for " and \ characters
if (ch = '"') then
while (exist(nextChar())) loop
if (ch = '"') then
nextChar();
return l_string;
end if;
if (ch = '\') then
nextChar();
if (ch = 'u') then
uffff := '';
for i in 1..4 loop
decnum := hex2dec(nextChar());
if (not isNumber(decnum)) then
error('Malformed Unicode character escape sequence');
end if;
uffff := uffff || ch;
end loop;
l_string := l_string || getUnicodeChar(uffff);
elsif (escapee(ch) is not null) then
l_string := l_string || escapee(ch);
else
exit;
end if;
else
l_string := l_string || ch;
end if;
end loop;
end if;
error('Bad string');
end;
/* @private
* skip whitespace
*/
procedure white
is
begin
while (exist(ch) and ch <= ' ') loop
nextChar();
end loop;
end;
/* @private
* validate a word (true, false or null)
*/
function validateWord return boolean
is
begin
case ch
when 't' then
nextChar('t');
nextChar('r');
nextChar('u');
nextChar('e');
return true;
when 'f' then
nextChar('f');
nextChar('a');
nextChar('l');
nextChar('s');
nextChar('e');
return true;
when 'n' then
nextChar('n');
nextChar('u');
nextChar('l');
nextChar('l');
return true;
else
error('Unexpected ''' || ch || '''');
end case;
end;
/* @private
* validate an array value
*/
function validateArray return boolean
is
l_result boolean := true;
begin
if (ch = '[') then
nextChar('[');
white();
if (ch = ']') then
nextChar(']');
return l_result; -- empty array
end if;
while (exist(ch)) loop
l_result := validate();
white();
if (ch = ']') then
nextChar(']');
return l_result;
end if;
nextChar(',');
white();
end loop;
end if;
error('Bad array');
end;
/* @private
* validate an object value
*/
function validateObject return boolean
is
l_result boolean := true;
l_key varchar2(1000);
l_keys array_t;
begin
if (ch = '{') then
nextChar('{');
white();
if (ch = '}') then
nextChar('}');
return l_result; -- empty object
end if;
while (exist(ch)) loop
l_key := stringKey();
white();
nextChar(':');
if (has_key(l_keys, l_key)) then
error('Duplicate key "' || l_key || '"');
end if;
add_key(l_keys, l_key);
l_result := validate();
white();
if (ch = '}') then
nextChar('}');
return l_result;
end if;
nextChar(',');
white();
end loop;
end if;
error('Bad object');
end;
/* @public
* validate a JSON value.
* It could be an object, an array, a string, a number, or a word.
*/
function validate return boolean
is
begin
white();
case ch
when '{' then
return validateObject();
when '[' then
return validateArray();
when '"' then
return validateString();
when '-' then
return validateNumber();
else
return case
when (ch >= '0' and ch <= '9') then validateNumber() else validateWord() end;
end case;
end;
/* @public
* unsafety validate JSON string (throw exception ora-20000)
*/
function unsafety_validate(source in varchar2) return boolean
is
l_result boolean;
begin
text := source;
atCh := 1;
ch := ' ';
l_result := validate();
white();
if (exist(ch)) then
error('Syntax error');
end if;
return l_result;
end;
/* @public
* safety validate JSON string (catch all exceptions)
*/
function safety_validate(source in varchar2) return boolean
is
l_result boolean;
begin
text := source;
atCh := 1;
ch := ' ';
l_result := validate();
white();
if (exist(ch)) then
error('Syntax error');
end if;
return l_result;
exception
when others then
return false;
end;
/* @public
* safety validate JSON string (catch all exceptions with error message)
*/
function safety_validate(source in varchar2,
errmsg in out varchar2) return boolean
is
l_result boolean;
begin
text := source;
atCh := 1;
ch := ' ';
l_result := validate();
white();
if (exist(ch)) then
error('Syntax error');
end if;
return l_result;
exception
when others then
errmsg := sqlerrm;
return false;
end;
begin
-- init
null;
end json_validator;
Пример использования данного пакета
declare
json_string varchar2(1000);
errmsg varchar2(32767);
begin
json_string := '{"number": 123456, "text": "active", "array": [], "object": {}}';
if json_validator.safety_validate(json_string, errmsg) then
dbms_output.put_line('JSON is valid');
else
dbms_output.put_line('JSON is not valid');
dbms_output.put_line(errmsg);
end if;
end;
Javascript. Unicode char by hex code
Ниже представлена реализация получения unicode-символа по шестнадцатеричному коду в методе getUnicodeChar утилитного объекта util.
// utility object
var util = {
// modulo
mod: function (a, b) {
return a % b;
},
// integer division
div: function (a, b) {
return (a - a % b) / b;
},
// convert hex to decimal number
hex2dec: function (hex) {
hex = '' + hex;
var result = 0,
dec, i, len;
for (i = 0, len = hex.length; i < len; i++) {
dec = parseInt(hex.charAt(i), 16);
if (!isFinite(dec)) {
break;
}
result = result * 16 + dec;
}
return result;
},
// convert decimal number to hex
dec2hex: function (number) {
number = +number;
var dec = 0,
result = '',
self = this;
while ((dec = self.mod(number, 16)) > 0) {
result = dec.toString(16) + result;
number = self.div(number, 16);
}
return result;
},
// get unicode char
getUnicodeChar: function (unicode) {
var unicodeChar = '',
uffff = 0,
self = this;
if (unicode.charAt(0) === '\\' && unicode.charAt(1) === 'u') {
uffff = self.hex2dec(unicode.substr(2));
}
return unicodeChar + String.fromCharCode(uffff);
}
};
console.log(util.getUnicodeChar('\\u041a')); // К
console.log(util.hex2dec('041a')); // 1050
console.log(util.dec2hex(1050)); // 41a
Стоит отметить, что методы hex2dec и dec2hex можно реализовать и более простым способом.
// convert hex to decimal number
function hex2dec(hex) {
return parseInt(hex, 16);
}
// convert decimal number to hex
function dec2hex(dec) {
return dec.toString(16);
}
console.log(hex2dec('041a')); // 1050
console.log(dec2hex(1050)); // 41a
// utility object
var util = {
// modulo
mod: function (a, b) {
return a % b;
},
// integer division
div: function (a, b) {
return (a - a % b) / b;
},
// convert hex to decimal number
hex2dec: function (hex) {
hex = '' + hex;
var result = 0,
dec, i, len;
for (i = 0, len = hex.length; i < len; i++) {
dec = parseInt(hex.charAt(i), 16);
if (!isFinite(dec)) {
break;
}
result = result * 16 + dec;
}
return result;
},
// convert decimal number to hex
dec2hex: function (number) {
number = +number;
var dec = 0,
result = '',
self = this;
while ((dec = self.mod(number, 16)) > 0) {
result = dec.toString(16) + result;
number = self.div(number, 16);
}
return result;
},
// get unicode char
getUnicodeChar: function (unicode) {
var unicodeChar = '',
uffff = 0,
self = this;
if (unicode.charAt(0) === '\\' && unicode.charAt(1) === 'u') {
uffff = self.hex2dec(unicode.substr(2));
}
return unicodeChar + String.fromCharCode(uffff);
}
};
console.log(util.getUnicodeChar('\\u041a')); // К
console.log(util.hex2dec('041a')); // 1050
console.log(util.dec2hex(1050)); // 41a
Стоит отметить, что методы hex2dec и dec2hex можно реализовать и более простым способом.
// convert hex to decimal number
function hex2dec(hex) {
return parseInt(hex, 16);
}
// convert decimal number to hex
function dec2hex(dec) {
return dec.toString(16);
}
console.log(hex2dec('041a')); // 1050
console.log(dec2hex(1050)); // 41a
PLSQL. Object type reflection
Возможно ли просматривать начинку объектных типов независимо от их типа. Для этого в Oracle есть поддержка таких универсальных типов как ANYTYPE, ANYDATA и ANYDATASET. Ниже представлен пример рефлексии объектных типов, с элементами типа VARCHAR2, NUMBER и DATE, при желании список поддерживаемых типов можно расширить (см. документацию).
-- sql
create or replace type order_t as object (
order_id number,
order_date date,
description varchar2(1000)
)
-- pl/sql
declare
v_order order_t := order_t(123456, sysdate, 'Description text');
v_anydata anydata;
-- print object information (reflection)
procedure objectInfo(p_object in out anydata) -- out for piecewise
is
l_typecode pls_integer;
l_anytype anytype;
l_result pls_integer;
l_varchar2 varchar2(32767);
l_number number;
l_date date;
-- type-level metadata
type typeinfo_r is record (
prec pls_integer
,scale pls_integer
,len pls_integer
,csid pls_integer
,csfrm pls_integer
,schema_name varchar2(30)
,type_name varchar2(30)
,version varchar2(30)
,count pls_integer
);
typeinfo typeinfo_r;
-- attribute-level metadata
type attrinfo_r is record (
prec pls_integer
,scale pls_integer
,len pls_integer
,csid pls_integer
,csfrm pls_integer
,attr_elt_type anytype
,aname varchar2(32767)
);
attrinfo attrinfo_r;
begin
-- get information for the ANYDATA instance
l_typecode := p_object.getType(l_anytype);
dbms_output.put_line('Typecode: ' || l_typecode);
if l_typecode = dbms_types.typecode_object then -- if given object
p_object.piecewise();
-- get type-level metadata
l_typecode := l_anytype.GetInfo(typeinfo.prec,
typeinfo.scale,
typeinfo.len,
typeinfo.csid,
typeinfo.csfrm,
typeinfo.schema_name,
typeinfo.type_name,
typeinfo.version,
typeinfo.count);
dbms_output.put_line('-------------------------------------');
dbms_output.put_line('Typename: ' || typeinfo.type_name);
dbms_output.put_line('Attributes: ' || typeinfo.count);
for i in 1..typeinfo.count loop -- loop by atrributes
-- get attribute-level metadata
l_typecode := l_anytype.getAttrElemInfo(i,
attrinfo.prec,
attrinfo.scale,
attrinfo.len,
attrinfo.csid,
attrinfo.csfrm,
attrinfo.attr_elt_type,
attrinfo.aname);
dbms_output.put_line('-------------------------------------');
dbms_output.put_line('Attribute: ' || attrinfo.aname);
dbms_output.put_line('Typecode: ' || l_typecode);
dbms_output.put_line('Length: ' || nvl(attrinfo.len, attrinfo.prec));
if l_typecode = dbms_types.typecode_varchar2 then -- varchar2
l_result := p_object.getVarchar2(c => l_varchar2);
dbms_output.put_line('Value: ' || l_varchar2);
elsif l_typecode = dbms_types.typecode_number then -- number
l_result := p_object.getNumber(num => l_number);
dbms_output.put_line('Value: ' || l_number);
elsif l_typecode = dbms_types.typecode_date then -- date
l_result := p_object.getDate(dat => l_date);
dbms_output.put_line('Value: ' || to_char(l_date, 'dd.mm.yyyy'));
else
raise_application_error(-20000, 'Unexpected ' || i || 'st attribute typecode: ' || l_typecode);
end if;
end loop;
end if;
end;
begin
v_anydata := anydata.convertObject(v_order);
objectInfo(v_anydata);
end;
Typecode: 108
-------------------------------------
Typename: ORDER_T
Attributes: 3
-------------------------------------
Attribute: ORDER_ID
Typecode: 2
Length: 0
Value: 123456
-------------------------------------
Attribute: ORDER_DATE
Typecode: 12
Length:
Value: 15.10.2015
-------------------------------------
Attribute: DESCRIPTION
Typecode: 9
Length: 1000
Value: Description text
-- sql
create or replace type order_t as object (
order_id number,
order_date date,
description varchar2(1000)
)
-- pl/sql
declare
v_order order_t := order_t(123456, sysdate, 'Description text');
v_anydata anydata;
-- print object information (reflection)
procedure objectInfo(p_object in out anydata) -- out for piecewise
is
l_typecode pls_integer;
l_anytype anytype;
l_result pls_integer;
l_varchar2 varchar2(32767);
l_number number;
l_date date;
-- type-level metadata
type typeinfo_r is record (
prec pls_integer
,scale pls_integer
,len pls_integer
,csid pls_integer
,csfrm pls_integer
,schema_name varchar2(30)
,type_name varchar2(30)
,version varchar2(30)
,count pls_integer
);
typeinfo typeinfo_r;
-- attribute-level metadata
type attrinfo_r is record (
prec pls_integer
,scale pls_integer
,len pls_integer
,csid pls_integer
,csfrm pls_integer
,attr_elt_type anytype
,aname varchar2(32767)
);
attrinfo attrinfo_r;
begin
-- get information for the ANYDATA instance
l_typecode := p_object.getType(l_anytype);
dbms_output.put_line('Typecode: ' || l_typecode);
if l_typecode = dbms_types.typecode_object then -- if given object
p_object.piecewise();
-- get type-level metadata
l_typecode := l_anytype.GetInfo(typeinfo.prec,
typeinfo.scale,
typeinfo.len,
typeinfo.csid,
typeinfo.csfrm,
typeinfo.schema_name,
typeinfo.type_name,
typeinfo.version,
typeinfo.count);
dbms_output.put_line('-------------------------------------');
dbms_output.put_line('Typename: ' || typeinfo.type_name);
dbms_output.put_line('Attributes: ' || typeinfo.count);
for i in 1..typeinfo.count loop -- loop by atrributes
-- get attribute-level metadata
l_typecode := l_anytype.getAttrElemInfo(i,
attrinfo.prec,
attrinfo.scale,
attrinfo.len,
attrinfo.csid,
attrinfo.csfrm,
attrinfo.attr_elt_type,
attrinfo.aname);
dbms_output.put_line('-------------------------------------');
dbms_output.put_line('Attribute: ' || attrinfo.aname);
dbms_output.put_line('Typecode: ' || l_typecode);
dbms_output.put_line('Length: ' || nvl(attrinfo.len, attrinfo.prec));
if l_typecode = dbms_types.typecode_varchar2 then -- varchar2
l_result := p_object.getVarchar2(c => l_varchar2);
dbms_output.put_line('Value: ' || l_varchar2);
elsif l_typecode = dbms_types.typecode_number then -- number
l_result := p_object.getNumber(num => l_number);
dbms_output.put_line('Value: ' || l_number);
elsif l_typecode = dbms_types.typecode_date then -- date
l_result := p_object.getDate(dat => l_date);
dbms_output.put_line('Value: ' || to_char(l_date, 'dd.mm.yyyy'));
else
raise_application_error(-20000, 'Unexpected ' || i || 'st attribute typecode: ' || l_typecode);
end if;
end loop;
end if;
end;
begin
v_anydata := anydata.convertObject(v_order);
objectInfo(v_anydata);
end;
Typecode: 108
-------------------------------------
Typename: ORDER_T
Attributes: 3
-------------------------------------
Attribute: ORDER_ID
Typecode: 2
Length: 0
Value: 123456
-------------------------------------
Attribute: ORDER_DATE
Typecode: 12
Length:
Value: 15.10.2015
-------------------------------------
Attribute: DESCRIPTION
Typecode: 9
Length: 1000
Value: Description text
Subscribe to:
Posts
(
Atom
)