On Github marlic7 / warsawjs-nodejs-and-oracle
Ruby Python Java Go Erlang Scala ???
Node.js
Projekt w Github: joeferner/node-oracle
oficjalnie jeszcze nie wspierany (jest procesowany PR)
instalacja z forka:npm install https://github.com/Bigous/node-oracledb.git
wczoraj tj. 17.11.2015 wydany release node-oracledb@1.4.0 Node.js 0.10, 0.12, 4.2 i 5.0
https://www.npmjs.com/package/node-dal https://github.com/marlic7/node-dal
Teraz poprzez przykłady omówię wybrane (ważniejsze) problemy, z którymi zetknąłem się realizując 2 projekty.
pool.getConnection(function(err, connection) { if (err) { cb(new Error(err)); return; } connection.execute('SELECT SYSDATE FROM DUAL', [], function(err, result) { if (err) { cb(new Error(err)); connection.release(function(err) { if (err) { cb(new Error(err), {only_log: true}); } }); return; } cb(null, result.rows[0][0]); connection.release(function(err) { if (err) { cb(new Error(err), {only_log: true}); } }); }); });1. pobranie połączenia z puli (j. błąd to cb i return) 2. wywołanie SQL (j. błąd to cb, zwolnienie połączenia do puli (z obsługą błędu) i return) 3. zwolnienie połączenia do puli i przekazanie wyniku zapytania do głównego cb
dal.selectOneValueSql('SELECT SYSDATE FROM DUAL', [], function(err, result) { if(err) { cb(new Error(err)); return; } cb(null, result); });
lub
dal.selectOneValue('DUAL', 'SYSDATE', [], function(err, result) { if(err) { cb(new Error(err)); return; } cb(null, result); });
var oracledb = require('oracledb'); oracledb.maxRows = 100; // (wartość domyślna)
connection.execute("SELECT * FROM employees", [], { maxRows: 1000 }, function(err, result) { // result.rows.length <= 1000 });maxRows - maksymalna liczba wierszy pobieranych przez execute() (gdy nie jest używany ResultSet). Wiersze powyżej tego limitu nie są pobierane. globalne zwiększenie tego limitu powoduje większą alokację pamięci na poziomie C++ dla każdego execute()
var oracledb = require('oracledb'); oracledb.prefetchRows = 100; // (wartość domyślna)
connection.execute("SELECT * FROM employees", [], { resultSet: true, prefetchRows: 200 }, function(err, result) { var allRows = []; function fetch() { var max = 200; result.resultSet.getRows(max, function(err, rows) { allRows = allRows.concat(rows); if (rows.length === max) { fetch(); } else { result.resultSet.close(function(err) { connection.release(function(err) { cb(null, allRows); }); }); } }); } fetch(); });przykład bez obsługi błędów - dla przejrzystości resultSet - używać gdy nie wiemy ile wierszy może być zwrócone, albo wiemy ale może się to zmieniać w czasie. Używać gdy potrzeba pobrać dużą liczbę wierszy. Wtedy optymalnie jest wykorzystać przetwarzanie strumieniowe. przykład: fetch 200 wierszy, preparacja wyjścia csv i flush chunk-a do CSV można też bez strumieni, jeżeli wierszy nie ma bardzo dużo i chcemy po prostu pobrać wszystkie (next slide)
dal.selectAllRowsSql("SELECT * FROM employees", [], function(err, result) { cb(null, allRows); });
lub
dal.selectAllRows({ tbl: 'employees', opt: { limit:10, page:5 }, cb: function(err, results) { cb(null, results); } });
var async = require('async'), oracledb = require('oracledb'), cfg = { user: "username", password: "password", connectString: "localhost/XE", poolMax: 10, poolMin: 2 }, sqls = [], i = 15; while(i--) { sqls.push('SELECT SYSDATE FROM DUAL'); } oracledb.createPool(cfg, function(err, pool) { var executeSql = function(sql, cb) { pool.getConnection(function(err, connection) { connection.execute(sql, [], function(err, results) { cb(null, results.rows[0][0]); }); }); }; async.map(sqls, executeSql, function(err, results) { callback(null, results); }); });
Wynik: ORA-24418: Nie można otworzyć kolejnych sesji.
przykłady bez obsługi błędów oraz bez zwalniania połączenia do puli - dla przejrzystości Wbudowana pula w driver natywny oracledb nie posiada aktualnie mechanizmów kolejki. Próba pobrania połączenia z puli w systuacji gdy wszystie połączenia pracują, kończy się niepowodzeniem.var async = require('async'), dalFactory = require('node-dal'), cfg = { connection: { user: "testy", password: "testy123", connectString: "localhost/XE", poolMax: 10, poolMin: 1 }, getConnMaxProbes: 100, // times getConnWaitMinTime: 200, // miliseconds getConnWaitMaxTime: 500 // miliseconds }, sqls = [], i = 15; while(i--) { sqls.push('SELECT SYSDATE FROM DUAL'); } dalFactory('oracledb', cfg, function(err, dal) { var executeSql = function(sql, cb) { dal.selectOneValueSql(sql, [], function(err, result) { cb(null, result); }); }; async.map(sqls, executeSql, function(err, results) { callback(null, results); }); });
Wynik: [data1, data2, ... , data15]
przykłady bez obsługi błędów - dla przejrzystości brakuje tylko obsługi błędów, w tym przypadku nie trzeba zwracać połącenia do puliOWA - PL/SQL Web Toolkit APEX - Oracle Application Express
process.env.UV_THREADPOOL_SIZE = 4; // Node.js default value
process.env.UV_THREADPOOL_SIZE = 10;
Any application that can be written in JavaScript, will eventually be written in JavaScript.
Jeff Atwood, the founder of stackoverflow.com Put your speaker notes here. You can see them pressing 's'.