Coder Social home page Coder Social logo

k2informaticsgmbh / erloci Goto Github PK

View Code? Open in Web Editor NEW
37.0 12.0 12.0 8.56 MB

Erlang Oracle native driver - DEPRECATED, see https://github.com/K2InformaticsGmbH/oranif instead

License: Apache License 2.0

GAP 0.63% Makefile 0.58% C++ 57.63% C 1.20% Erlang 39.92% Python 0.04%
instantclient erlang thread-pool erlang-driver c-plus-plus oci database deprecated deprecated-repo obselete

erloci's Introduction

DEPRECATED

This is no longer supported, please consider using oranif instead.

erloci - An Erlang driver for the Oracle Call Interface

Build Status Coverage Status

Users

K2 Informatics GmbH Privat Bank, Ukraine

Setup the development system

Create a environment variable OTPROOT pointing to erlang installation directory, e.g. - in linux (if installed from RPM) its usually /usr/lib/erlang. Download from Oracle the following libraries (for matching os and platfrom for the development system)

  1. instantclient-basic
  2. instantclient-sdk

Windows

Unzip both into a directory and create the following enviroment variable E.g. - if your instant client library version is 12.1 and you have unzipped 'instantclient-basic-windows*.zip' to C:\Oracle\instantclient\instantclient_12_1 then the sdk should be at C:\Oracle\instantclient\instantclient_12_1\sdk
The include headers will be at C:\Oracle\instantclient\instantclient_12_1\sdk\include and static libraries at C:\Oracle\instantclient\instantclient_12_1\sdk\lib\msvc (note the path for VS project configuration later)

Linux / Mac OS X

Required system libraries

libevent
libevent-devel

Use rpms (recomended) to install basic and sdk. The default install path is usually (for x86_64 architecture) For Mac you may use Homebrew (http://brew.sh) as package manager to install it.

OCI Headers     : /usr/include/oracle/12.1/client64/
OCI Libraries   : /usr/lib/oracle/12.1/client64/lib/

Create Environment variables

INSTANT_CLIENT_LIB_PATH     = path to oci libraries
INSTANT_CLIENT_INCLUDE_PATH = path to oci headers
ERL_INTERFACE_DIR           = path to erl_interface or erlang installation

Example .bashrc snippet:

...
INSTANT_CLIENT_LIB_PATH=$(find /usr/lib/oracle/ -type d -name client64)/lib
INSTANT_CLIENT_INCLUDE_PATH=$(find /usr/include/oracle/ -type d -name client64)
ERL_INTERFACE_DIR=$(find /usr/lib/erlang/lib/ -type d -name erl_interface-*)

export INSTANT_CLIENT_LIB_PATH
export INSTANT_CLIENT_INCLUDE_PATH
export ERL_INTERFACE_DIR
...

For example:

(x64 Fedora)
INSTANT_CLIENT_LIB_PATH     = /usr/lib/oracle/12.1/client64/lib/
INSTANT_CLIENT_INCLUDE_PATH = /usr/include/oracle/12.1/client64/
ERL_INTERFACE_DIR           = /usr/lib64/erlang/lib/erl_interface-3.7.15


(x64 Windows 7)
INSTANT_CLIENT_LIB_PATH     = C:\Oracle\instantclient\instantclient_12_1\
ERL_INTERFACE_DIR           = C:\Program Files\erlang\erl5.10.4\lib\erl_interface-3.7.15

Ubuntu (14.04.2 LTS 'trusty')

sudo apt-get install libevent-dev
sudo apt-get install alien dpkg-dev debhelper build-essential
sudo alien oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
sudo alien oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm
sudo dpkg -i oracle-instantclient12.1-basic_12.1.0.2.0-2_amd64.deb
sudo dpkg -i oracle-instantclient12.1-devel_12.1.0.2.0-2_amd64.deb

~/.profile
export INSTANT_CLIENT_LIB_PATH="/usr/lib/oracle/12.1/client64/lib/"
export INSTANT_CLIENT_INCLUDE_PATH="/usr/include/oracle/12.1/client64/"
export ERL_INTERFACE_DIR="/usr/lib/erlang/lib/erl_interface-3.8.2"

Compiling

We assume you have rebar3 somewhere on your path. Rebar3 will take care of the Erlang and C++ sources. rebar3 compile Please check the rebar3 documentation for how to add erloci as a dependency to your project.

DEPRICATION WARNING Visual Studio 2008 and Visual Studio 2013 are no longer supported please build with Visual Studio 2017 (Community Edition) instead

Issue rebar3 compile as usual; then don't forget to revert temporarily changed vcxproj files: git reset --hard.

NOTE: Setting the environment variables for the comand line tools might be needed: "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64

3rd party dependencies

Threadpool

The threadpool code (threadpool.cpp/h) is developed by Mathias Brossard [email protected]. His threadpool library is hosted at https://github.com/mbrossard/threadpool. This library is unused (not linked) in a Windows environment. For an easier installation process we include the required threadpool files in the erloci repo. So this is NOT a dependency you have to resolve by yourself.

Oracle Call Interface (OCI)

OCI provides a high performance, native 'C' language based interface to the Oracle Database. There is no ODBC layer between your application and the database. Since we don't want to distribute the Oracle Code you MUST download the OCI Packages (basic and devel) from the Oracle Website: http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html.

Compile ERLOCI in Windows command line

Make sure you have MSbuild.exe in path. After that rebar3 compile will take care the rest. Currently erloci can only be build with VS2008.

Erlang to/from Oracle datatype mapping (currently)

oracle erlang
SQLT_INT integer()
SQLT_CHR,SQLT_AFC binary()
SQLT_FLT float()
SQLT_IBDOUBLE float()
SQLT_BIN binary()
SQLT_DAT binary()
SQLT_TIMESTAMP binary()
SQLT_TIMESTAMP_LTZ binary()
SQLT_INTERVAL_YM binary()
SQLT_INTERVAL_DS binary()
SQLT_IBFLOAT float()

Eunit test

The database user <<db_user>> must have at least the following privileges:

-- Roles
GRANT CONNECT TO <<db_user>>;
GRANT RESOURCE TO <<db_user>>;
ALTER USER <<db_user>> DEFAULT ROLE ALL;
-- System Privileges
GRANT ALTER SESSION TO <<db_user>>;
GRANT ALTER SYSTEM TO <<db_user>>;
GRANT CREATE ANY DIRECTORY TO <<db_user>>;
GRANT CREATE DATABASE LINK TO <<db_user>>;
GRANT CREATE SEQUENCE TO <<db_user>>;
GRANT CREATE SESSION TO <<db_user>>;
GRANT CREATE SYNONYM TO <<db_user>>;
GRANT CREATE VIEW TO <<db_user>>;
GRANT DROP ANY DIRECTORY TO <<db_user>>;
-- Object Privileges
GRANT EXECUTE ON SYS.DBMS_STATS TO <<db_user>>;
GRANT SELECT ON SYS.GV_$PROCESS TO <<db_user>>;
GRANT SELECT ON SYS.GV_$SESSION TO <<db_user>>;

The Oracle connection information are taken from the file connect.config in directory test. Please change it to point to your database before executing the steps below:

  1. rebar3 compile
  2. rebar3 eunit

API Description through examples

Create a new erloci environment

OciPort = erloci:new([{logging, false}, {env, []}]),

Get an OCI Session

Tns = <<"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=XE)))">>,
Pswd= <<"XXXXXX">>,
User= <<"User">>,
OciSession = OciPort:get_session(Tns, User, Pswd),

Prepare an OCI Statement

SelStmt = OciSession:prep_sql("SELECT lastname, firstname from testtable where personid > :a "),

Bind Variable types

SelStmt:bind_vars([{<<":a">>,'SQLT_INT'}]),

Execute the statement with bind values

SelStmt:exec_stmt([{1}]),

Returns: {cols, [Definition]} where Definition is {ColumnName, ColumnType, ColumnSize, Precision, Scale}

Fetch result rows

SelStmt:fetch_rows(NumRows)

Returns: {{rows, [Row]}, IsComplete}

CHANGE LOG

0.0.2

  1. STL term class for wrapping erlang term
  2. Native process redesigned to OO
  3. Support Variable binding for Input
  4. Concurrent connection and statements
  5. Common test for load testing

0.1.0

  1. Compiled with rebar3
  2. CommonTests restructured

0.1.1

  1. Compile with Visual Studio 2017 Community Edition tool chain

Work-In-Progess

  1. Testing and stabilization
  2. Wiki

TODOs

  1. In/Out bind variables and arrays

erloci's People

Contributors

acautin avatar c-bik avatar k2informatics avatar karlkeiser avatar nkezhaya avatar sergej-klimenko avatar shamis avatar stoch avatar tgdriph3 avatar ttyesl avatar walter-weinmann avatar zsoltm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

erloci's Issues

Hour,Minutes,Seconds increased by 1

cc : @ElMaxo

> SelStmt = OciSession:prep_sql(
    "select to_char(sysdate, 'DD-MM-YYYY HH24:MI:SS'), sysdate from dual").
> SelStmt:exec_stmt().
{cols,[{<<"TO_CHAR(SYSDATE,'DD-MM-YYYYHH24:MI:SS')">>,
        'SQLT_CHR',38,0,0},
       {<<"SYSDATE">>,'SQLT_DAT',7,0,0}]}
> SelStmt:fetch_rows(100).
{{rows,[[<<"29-06-2017 10:58:18">>,
         <<120,117,6,29,11,59,19>>]]},
 true}
> oci_util:oradate_to_str(<<120,117,6,29,11,59,19>>).
"****.06.29 11:59:19"

Hours, minutes and seconds shifted by 1

Statements not reusable after transient error

Current

application:stop(erloci).
application:start(erloci).
f().
InsSql = <<"insert into test values(:P_VALUE)">>.
InsBind = [{<<":P_VALUE">>, in,'SQLT_INT}].
OciPort = erloci:new([{env,[{"NLS_LANG","GERMAN_SWITZERLAND.AL32UTF8"}]}]).
Sess = OciPort:get_session(<<"(DESCRIPTION =(ENABLE=BROKEN)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
                              (HOST=1.1.1.1)(PORT = 1111)))(CONNECT_DATA=(SERVER=DEDICATED)
                              (SERVICE_NAME=XE)))">>, <<"user">>, <<"password">>).
InsStmt = Sess:prep_sql(InsSql).
ok = InsStmt:bind_vars(InsBind).

InsStmt:exec_stmt([{1}]).
{error,{1,
        <<"ORA-00001: unique constraint (SCOTT.TEST_UNIQUE) violated\n">>}}

InsStmt:exec_stmt([{1}]).
** exception error: no function clause matching
  oci_port:'-collect_grouped_bind_request/6-fun-0-'({error,0,<<"invalid statement handle">>},[])
                                                                    (src/oci_port.erl, line 180)
     in function  lists:foldl/3 (lists.erl, line 1262)
     in call from oci_port:collect_grouped_bind_request/6 (src/oci_port.erl, line 180)

Expected

...
InsStmt:exec_stmt([{1}]).
{error,{1,
        <<"ORA-00001: unique constraint (SCOTT.TEST_UNIQUE) violated\n">>}}
InsStmt:exec_stmt([{1}]).
{error,{1,
        <<"ORA-00001: unique constraint (SCOTT.TEST_UNIQUE) violated\n">>}}

InsStmt:exec_stmt([{2}]).
{rowids,[<<"AAAS66AABAAALLRAAA">>]}
InsStmt:exec_stmt([{2}]).
{error,{1,
        <<"ORA-00001: unique constraint (SCOTT.TEST_UNIQUE) violated\n">>}}

How to set autocommit to false when runs sql.

We have some sql for create 2 tables.

sql1 = "CREATE TABLE schema_migrations (version NUMBER, inserted_at TIMESTAMP)"

and next

sql2 = "CREATE TABLE schema_migrations1 (version NUMBER, inserted_at TIMESTAMP)"

I have my sessions in pool:

    oci = :erloci.new([Enum.into(opts, %{})])
    session = oci.get_session(credentials[:tns], credentials[:user], credentials[:password])
    {:ok, session}

Next i run some command:

session.prep_sql(sql1).exec_stmt()
session.prep_sql(sql2).exec_stmt()

It's works, but i want wrap in transaction...

session.prep_sql("BEGIN").exec_stmt()
session.prep_sql(sql1).exec_stmt()
session.prep_sql(sql2).exec_stmt()
session.prep_sql("COMMIT").exec_stmt()

How i can do it?

reading RAW fields is truncating at byte 0

Create Table:

create table raw_clob(col_raw raw(2000))

Note: data is corrupted when read through select!

StmtInsert = OciSession:prep_sql(<<"insert into raw_clob (col_raw) values (:col_raw)">>).
ok = StmtInsert:bind_vars([{<<":col_raw">>, 'SQLT_BIN'}]).
Data = <<1,2,3,4,0,0,0,5,6,7,8>>,
{rowids, [_]} = StmtInsert:exec_stmt([{Data}]).

SelStmt = OciSession:prep_sql("select col_raw from raw_clob").
> {cols, _} = SelStmt:exec_stmt().
{cols,[{<<"COL_RAW">>,'SQLT_BIN',2000,0,0}]}

> SelStmt:fetch_rows(100).
{{rows,[[<<1,2,3,4>>]]},true}

Root Cause

  1. cur_clm.dlen + 1 is used to allocate buffer for RAW which is always (for the raw_clob table above) 2000.
    case SQLT_BIN: // RAW
    cur_clm.row_valp = new unsigned char[cur_clm.dlen + 1];
    memset(cur_clm.row_valp, 0, (cur_clm.dlen + 1)*sizeof(unsigned char));
    cur_clm.rtype = LCL_DTYPE_NONE;
    OCIDEF(SQLT_BIN, "SQLT_BIN");
    break;
    due to incorrect use of OCIAttrGet(OCI_DTYPE_PARAM, OCI_ATTR_DATA_SIZE) API to get the value in cur_clm.dlen
    checkerr(&r, OCIAttrGet((dvoid*) mypard, (ub4) OCI_DTYPE_PARAM,
    (dvoid*) &(cur_clm.dlen), (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE,
    (OCIError*)_errhp));
  2. Eventually hoever, strlen is used in
    case SQLT_BIN:
    case SQLT_RID:
    case SQLT_AFC:
    case SQLT_STR: {
    size_t str_len = strlen((char*)(_columns[i]->row_valp));
    (*intf.append_string_to_list)((char*)(_columns[i]->row_valp), str_len, row);
    memset(_columns[i]->row_valp, 0, str_len);
    break;
    }
    to determine real data length causing the truncation when binary contains 0 (\0 as string termination character)

Very long ROWIDs for index organized tables

Hi Bikram

it seems that Oracle 12 uses very long and dynamic rowids for certain tables (e.g. index organized tables):

image

Please check the bufferspace allocation for queries with columns of type ROWID

Timestamp fractional seconds internal oracle representation.

Hi I am seeing wrong results when using oci_util:from_dts/1 function for the fractional part. The problem seems to be matching using little endian instead of big when decoding the value.

Also #5 doesn't seem to be correct as I can read the data in binary format.

Support oracle 11.2.0.3.0?

hi, i used the rpms:
oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm

and the ~/.bash_profile in centos6.5 is
export INSTANT_CLIENT_LIB_PATH=/usr/lib/oracle/11.2/client64/lib/
export INSTANT_CLIENT_INCLUDE_PATH=/usr/include/oracle/11.2/client64/
export ERL_INTERFACE_DIR=/usr/local/lib/erlang/lib/erl_interface-3.7.20

when i exe rebar compile
the error is that:
/usr/bin/ld: cannot find -lons
collect2: ld returned 1 exit status
make: *** [priv/ocierl] Error 1
ERROR: Command [compile] failed!

so, i found that libons.so isnot exist in /usr/lib/oracle/11.2/client64/lib/
Because the libs were changed in oracle12, but my db version is 11g.
how to fix it?
thx

Starting oci_port throws SIGABRT exception

OS: RedHat 5
Erlang: r17.3
Oracle 12.1

When ever I start oci_port:start_link([{logging, true}]) it throws the exception below:

24.10.2014 14:51:22.494166 [info] [OCI] {oci_port,,361} started log disabled new port:
[{name,"./priv/ocierl"},
{links,[<0.37.0>]},
{id,6248},
{connected,<0.37.0>},
{input,0},
{output,19},
{os_pid,12823}]
24.10.2014 14:51:22.494406 [debug] [OCI] Waiting for peer to connect on 51586
24.10.2014 14:51:22.516756 [debug] [OCI] Connection from 35261 to 51586
{oci_port,<0.37.0>}
3> 24.10.2014 14:51:22.517253 [info] [OCI] {c_src/erloci_drv/erloci.cpp,main,73} Port process configs : erlang term max size 0x00040000 bytes, logging enabled, TCP port for logs 5158
terminate called after throwing an instance of 'intf_ret'

=ERROR REPORT==== 24-Oct-2014::14:51:22 ===
** Generic server <0.37.0> terminating
** Last message in was {#Port<0.781>,{exit_status,134}}
** When Server state == {state,#Port<0.781>,false,0,
{oci_logger,<0.38.0>},
undefined}
** Reason for termination ==
** {port_exit,{'SIGABRT',core,"Abort"}}
** exception error: {port_exit,{'SIGABRT',core,"Abort"}}
3>

Cursor-limit problem on bulk insert.

I used the following code to test performance [Use p(1000), for example]. But after some successful operations, server rejects further insertions with ORA-01000 error.
Please tell me what is wrong. Thanks.

t.erl:

-module(t).
-export([p/1,p_p/2]).

p(N) ->
application:start(erloci),
OciPort = erloci:new([{logging, false}]),
Tns= <<"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=10.143.132.100)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=bimstest)))">>,
User= <<"bill">>,
Pswd= <<"bill123">>,
OciSession = OciPort:get_session(Tns, User, Pswd),
process_flag(trap_exit, true),
p_create(N,OciSession),
p_exit(N).

p_create(0,_) ->
ok;
p_create(N,OciSession) ->
spawn_link(?MODULE,p_p,[N,OciSession]),
p_create(N-1,OciSession).

p_p(N,OciSession) ->
S=iolist_to_binary(["insert into test_2 values(",integer_to_list(N),",",integer_to_list(N),")"]),
Stmt=OciSession:prep_sql(S),
io:format("~p |-~p--| pn",[S,Stmt,Stmt:exec_stmt()]),
case Stmt:close() of
ok ->
io:format("Statement close ok!~n");
Err ->
io:format("Statement close err:pn",[Err])
end.

p_exit(0) ->
ok;
p_exit(N) ->
receive
{'EXIT',_FromPid,_Reason} ->
p_exit(N-1);
_ ->
p_exit(N)
end.

Unoptimized oci_util:to_num

> dderloci_utils:oranumber_encode(<<"10.5">>).
<<3,193,11,51>> % Compact represetation
> dderloci_utils:oranumber_encode(<<"10.500">>).
<<3,193,11,51>> % Compact represetation (automatic trailing zeros removal)
> oci_util:from_num(<<3,193,11,51>>).   
"10.5"
> float_to_list(10.5, [{decimals,4}]).
"10.5000"
> oci_util:to_num(float_to_list(10.5, [{decimals,4}])).
<<4,193,11,51,1>> % Trailing zeros preserved
> oci_util:from_num(<<4,193,11,51,1>>).
"10.500"

How to define character set on connect

There are some unicode data (utf8) in oracle db. In order to get them properly,I hope I need to define charset when connecting to db. Otherwise I'm getting a line of questions marks for utf8 data. Database is already configured to use AL32UTF8. Does erloci supports that? I tried going through the code. but couldn't find a way to define charset.

Crash while closing session on ping failure

11:30.998000 [error] {oci_port,,413} Abnormal termination of {function_clause,
                            [{gen_server,reply,
                                 [<0.255.0>,ok],
                                 [{file,"gen_server.erl"},{line,240}]},
                             {oci_port,handle_info,2,
                                 [{file,"src/oci_port.erl"},{line,377}]},
                             {gen_server,try_dispatch,4,
                                 [{file,"gen_server.erl"},{line,615}]},
                             {gen_server,handle_msg,5,
                                 [{file,"gen_server.erl"},{line,681}]},
                             {proc_lib,init_p_do_apply,3,
                                 [{file,"proc_lib.erl"},{line,239}]}]}

=ERROR REPORT==== 17-Mar-2017::08:11:30 ===
** Generic server <0.255.0> terminating
** Last message in was {#Port<0.30613>,
                        {data,<<131,104,3,109,0,0,0,27,131,103,100,0,13,110,
                                111,110,111,100,101,64,110,111,104,111,115,
                                116,0,0,0,255,0,0,0,0,0,97,3,100,0,2,111,107>>}}
** When Server state == {state,#Port<0.30613>,false,1,
                               {oci_logger,<0.256.0>},
                               undefined,1000,#Ref<0.0.3.1309>}
** Reason for termination ==
** {function_clause,[{gen_server,reply,
                                 [<0.255.0>,ok],
                                 [{file,"gen_server.erl"},{line,240}]},
                     {oci_port,handle_info,2,
                               [{file,"src/oci_port.erl"},{line,377}]},
                     {gen_server,try_dispatch,4,
                                 [{file,"gen_server.erl"},{line,615}]},
                     {gen_server,handle_msg,5,
                                 [{file,"gen_server.erl"},{line,681}]},
                     {proc_lib,init_p_do_apply,3,
                               [{file,"proc_lib.erl"},{line,239}]}]}

String out variable values are not trimmed to correct size

PlSql = <<"BEGIN  :p_res1 := 'This is a test1';  :p_res2 := 'This is a test2'; END;">>.
PlSqlBindVars = [{<<":p_res1">>,out,'SQLT_CHR'},{<<":p_res2">>,out,'SQLT_CHR'}].
PlSqlStmt = OciSession:prep_sql(PlSql).
ok = PlSqlStmt:bind_vars(PlSqlBindVars).
PlSqlStmt:exec_stmt([{<<"                          ">>,<<"                          ">>}], 1).
> {executed,1,
          [{<<":p_res1">>,<<"This is a test1           ">>},
           {<<":p_res2">>,<<"This is a test2           ">>}]}
ok = PlSqlStmt:close().

OCI_SESSGET_SPOOL supportivity

I'm looking for the pool facility provided in c-bik / erloci as
{ok, Pool} = oci_session_pool:start_link("127.0.0.1", 1521, {service, "db.local"}, "dbauser", "supersecret",[]).

But I couldn't find it here. I can see OCISessionGet()'s mode is OCI_DEFAULT.

OTP 18 warnings

oci_logger.erl:95: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
oci_logger.erl:112: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
oci_logger.erl:120: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
Compiled src/oci_logger.erl
Compiled src/oci_util.erl
erloci.erl:48: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:48: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:48: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:48: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:49: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:49: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:49: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.
erloci.erl:49: Warning: erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" chapter of the ERTS User's Guide for more information.

Error starting a session

Hi,

Thanks for doing massive work on this driver!
I've tried using it and have issues establishing connection. Here's the log:

27.09.2017 21:32:36.094314 [debug] [_OCI_] {oci_logger,,71} ---- ERLOCI PORT PROCESS LOGGER ----
27.09.2017 21:32:36.097670 [debug] [_OCI_] {oci_port,,292} LD_LIBRARY_PATH = .../Projects/milo/_build/dev/lib/erloci/priv
27.09.2017 21:32:36.098060 [debug] [_OCI_] {oci_port,,300} Extra Env :[]
27.09.2017 21:32:36.098455 [debug] [_OCI_] {oci_port,,310} Executable "/Projects/milo/_build/dev/lib/erloci/priv/ocierl"
27.09.2017 21:32:36.098859 [debug] [_OCI_] {oci_port,,311} Options :[{packet,4},
          binary,exit_status,use_stdio,
          {args,["262144","true","55461"]},
          {env,[{"LD_LIBRARY_PATH",
                 "/usr/lib/oracle/12.1/client64/lib:/Projects/milo/_build/dev/lib/erloci/priv"}]}]
27.09.2017 21:32:36.099386 [debug] [_OCI_] {oci_port,,325} started log disabled new port:
[{name,"/Projects/milo/_build/dev/lib/erloci/priv/ocierl"},
 {links,[<0.433.0>]},
 {id,85392},
 {connected,<0.433.0>},
 {input,0},
 {output,19},
 {os_pid,251}]
27.09.2017 21:32:36.099857 [debug] [_OCI_] {oci_logger,,116} 27.09.2017 21:32:36.099829 Waiting for peer to connect on 55461
27.09.2017 21:32:36.107492 [debug] [_OCI_] {oci_logger,,124} 27.09.2017 21:32:36.107444 Connection from 57618 to 55461
27.09.2017 21:32:36.108115 [info] [_OCI_] {c_src/erloci_drv/erloci.cpp,main,83} [251] Port process configs : erlang term max size 0x00040000 bytes, logging enabled, TCP port for logs 55461, NLS_LANG
27.09.2017 21:32:36.111050 [info] [_OCI_] {c_src/erloci_lib/ocisession.cpp,config,69} OCI Initialize
27.09.2017 21:32:36.112281 [info] [_OCI_] {c_src/erloci_drv/command.cpp,change_log_flag,46} Disabling logging..
27.09.2017 21:32:36.112370 [debug] [_OCI_] {oci_port,,369} no reply for log_disabled
** (exit) exited in: :gen_server.call(#PID<0.433.0>, {:port_call, [2, "(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp) (HOST=127.0.0.1) (PORT=4421)) (CONNECT_DATA=(SID=sid_name)))", "user", nil, "nonode@nohost:<0.429.0>"]}, :infinity)
    ** (EXIT) an exception was raised:
        ** (FunctionClauseError) no function clause matching in :oci_port.handle_result/3
            (erloci) /Projects/milo/deps/erloci/src/oci_port.erl:428: :oci_port.handle_result(0, {<<131, 104, 2, 103, 100, 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, 0, 1, 173, 0, 0, 0, 0, 0, 114, 0, 3, 100, 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, ...>>, 2}, {:oci_logger, #PID<0.434.0>})
            (erloci) /Projects/milo/deps/erloci/src/oci_port.erl:367: :oci_port.handle_info/2
            (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
            (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
            (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
    (stdlib) gen_server.erl:214: :gen_server.call/3
    (erloci) /Projects/milo/deps/erloci/src/oci_port.erl:82: :oci_port.get_session/5
    (milo) lib/milo/repo.ex:7: Milo.Repo.all/1
iex(1)>
21:32:36.122 [error] GenServer #PID<0.433.0> terminating
** (FunctionClauseError) no function clause matching in :oci_port.handle_result/3
    (erloci) /Projects/milo/deps/erloci/src/oci_port.erl:428: :oci_port.handle_result(0, {<<131, 104, 2, 103, 100, 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, 0, 1, 173, 0, 0, 0, 0, 0, 114, 0, 3, 100, 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, ...>>, 2}, {:oci_logger, #PID<0.434.0>})
    (erloci) /Projects/milo/deps/erloci/src/oci_port.erl:367: :oci_port.handle_info/2
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {#Port<0.10674>, {:data, <<131, 104, 2, 109, 0, 0, 0, 61, 131, 104, 2, 103, 100, 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, 0, 1, 173, 0, 0, 0, 0, 0, 114, 0, 3, 100, 0, 13, 110, 111, 110, 111, 100, ...>>}}
State: {:state, #Port<0.10674>, false, 0, {:oci_logger, #PID<0.434.0>}, :undefined, 0, :undefined}

compile failed in my mac

~/erlang/research/erloci (master) 326h18m $ rebar co
==> erloci (compile)
c++ -ggdb -Wall -I/Users/homeway/erlang/erts/17.3/lib/erl_interface-3.7.18/include  -Ic_src/erloci_drv -Ic_src/erloci_lib -I/Users/homeway/Applications/oracle_client_sdk_11_2/sdk/include   -c -o c_src/erloci_drv/threads.o c_src/erloci_drv/threads.cpp
c_src/erloci_drv/threads.cpp:181:3: error: use of undeclared identifier 'pthread_yield'
                pthread_yield();
                ^
1 error generated.
make: *** [c_src/erloci_drv/threads.o] Error 1
ERROR: Command [compile] failed!

Data types mapping

Please, add data types mapping (Oracle <--> Erlang) to documentation for reference.

SQLT_VNU as out parameter is not supported

Works:

PlSql = <<"BEGIN :p_Absolute:=round(abs(:p_val1),0); :p_Floor:=round(floor(:p_val2),0); END;">>.
PlSqlBindVars = [{<<":p_val1">>,in,'SQLT_VNU'},{<<":p_val2">>,in,'SQLT_VNU'},
{<<":p_Absolute">>,out,'SQLT_INT'},{<<":p_Floor">>,out,'SQLT_INT'}].
PlSqlStmt = OciSession:prep_sql(PlSql).
ok = PlSqlStmt:bind_vars(PlSqlBindVars).
PlSqlStmt:exec_stmt([{oci_util:to_num("-5.5"), oci_util:to_num("4.9"),0,0}], 1).
> {executed,1,[{<<":p_Absolute">>,6},{<<":p_Floor">>,4}]}
ok = PlSqlStmt:close().

Doesn't work:

PlSql = <<"BEGIN :p_Absolute := abs(:p_val1); :p_Floor := floor(:p_val2); END;">>.
PlSqlBindVars = [{<<":p_val1">>,in,'SQLT_VNU'},{<<":p_val2">>,in,'SQLT_VNU'},
                           {<<":p_Absolute">>,out,'SQLT_VNU'},{<<":p_Floor">>,out,'SQLT_VNU'}].
PlSqlStmt = OciSession:prep_sql(PlSql).
ok = PlSqlStmt:bind_vars(PlSqlBindVars).
PlSqlStmt:exec_stmt([{oci_util:to_num("-5.5"), oci_util:to_num("4.9"),
                      oci_util:to_num("-100.100"), oci_util:to_num("-100.100")}], 1).
> {error,{0,
        <<"[ocistmt::execute:763] unsupporetd type 6\n">>}}
ok = PlSqlStmt:close().

Missing values of bound parameters on stmt reuse

Following is an example of writing values and then reading the same back and checking for differences

Vars = [{<<":P_CON_ID">>, in,'SQLT_CHR'}, {<<":P_CON_ACID">>, in,'SQLT_CHR'}, {<<":P_CON_CONSOL">>, in,'SQLT_CHR'}, {<<":P_CON_DATEBLOCK">>, in,'SQLT_CHR'},{<<":P_CON_DATEEND">>, in,'SQLT_CHR'}, {<<":P_CON_DATESTART">>, in,'SQLT_CHR'}, {<<":P_CON_ESID">>, in,'SQLT_CHR'}, 
  {<<":P_CON_ESTID">>, in,'SQLT_CHR'},{<<":P_CON_ETID">>, in,'SQLT_CHR'}, {<<":P_CON_HDGROUP">>, in,'SQLT_CHR'}, {<<":P_CON_IGNORE_DUOBILL">>, in,'SQLT_CHR'}, {<<":P_CON_IWRS">>, in,'SQLT_CHR'},{<<":P_CON_MFGR">>, in,'SQLT_CHR'}, {<<":P_CON_MFLID">>, in,'SQLT_CHR'}, 
  {<<":P_CON_MINCHARGE">>, in,'SQLT_CHR'}, {<<":P_CON_MOROAMINGPROM">>, in,'SQLT_CHR'},{<<":P_CON_MTROAMINGPROM">>, in,'SQLT_CHR'}, {<<":P_CON_NAME">>, in,'SQLT_CHR'}, {<<":P_CON_PMID">>, in,'SQLT_CHR'}, {<<":P_CON_PRICE">>, in,'SQLT_CHR'},{<<":P_CON_PRICEHG">>, in,'SQLT_CHR'}, 
  {<<":P_CON_PRICEINT">>, in,'SQLT_CHR'}, {<<":P_CON_PRICEMOFN">>, in,'SQLT_CHR'}, {<<":P_CON_PROTOCOL">>, in,'SQLT_CHR'},{<<":P_CON_PSCALL">>, in,'SQLT_CHR'}, {<<":P_CON_RSID">>, in,'SQLT_CHR'}, {<<":P_CON_SHORTID">>, in,'SQLT_CHR'}, {<<":P_CON_TARID">>, in,'SQLT_CHR'},
  {<<":P_CON_THROUGPUT">>, in,'SQLT_CHR'}].

USql = <<"begin gpsh_tpac_con_put(:P_CON_ID,:P_CON_ACID,:P_CON_CONSOL,:P_CON_DATEBLOCK,:P_CON_DATEEND,:P_CON_DATESTART,:P_CON_ESID,:P_CON_ESTID,:P_CON_ETID,:P_CON_HDGROUP,:P_CON_IGNORE_DUOBILL,:P_CON_IWRS,:P_CON_MFGR,:P_CON_MFLID,:P_CON_MINCHARGE,:P_CON_MOROAMINGPROM,:P_CON_MTROAMINGPROM,:P_CON_NAME,:P_CON_PMID,:P_CON_PRICE,:P_CON_PRICEHG,:P_CON_PRICEINT,:P_CON_PRICEMOFN,:P_CON_PROTOCOL,:P_CON_PSCALL,:P_CON_RSID,:P_CON_SHORTID,:P_CON_TARID,:P_CON_THROUGPUT); end;">>.

RSql = <<"select * from GPSH_TPAC_CON_JSON where CKEY = :P_CON_ID">>.

f(OciPort).
f(Sess).
f(UpdStmt).
f(ConJsonStmt).
f(Diff).

OciPort = erloci:new([{env,[{"NLS_LANG","GERMAN_SWITZERLAND.AL32UTF8"}]}]).
Sess = OciPort:get_session(<<"(DESCRIPTION =(ENABLE=BROKEN)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=1.1.1.1)(PORT = 2222)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)))">>, <<"a">>, <<"b">>).
UpdStmt = Sess:prep_sql(USql).
ok = UpdStmt:bind_vars(Vars).
ConJsonStmt = Sess:prep_sql(RSql).
ok = ConJsonStmt:bind_vars([{<<":P_CON_ID">>, in, 'SQLT_CHR'}]).
NValue = #{<<"CON_ACID">> => <<"546X0XM3HJ">>,
  <<"CON_CONSOL">> => <<"50254">>,
  <<"CON_DATEBLOCK">> => <<>>,
  <<"CON_DATEEND">> => <<>>,
  <<"CON_DATESTART">> => <<"2016-06-15T00:00:00Z">>,
  <<"CON_ESID">> => <<"A">>,
  <<"CON_ESTID">> => <<>>,
  <<"CON_ETID">> => <<"LAC">>,
  <<"CON_HDGROUP">> => <<"false">>,
  <<"CON_IGNORE_DUOBILL">> => <<"false">>,
  <<"CON_IWRS">> => <<>>,
  <<"CON_MFGR">> => <<>>,
  <<"CON_MFLID">> => <<>>,
  <<"CON_MINCHARGE">> => <<"200">>,
  <<"CON_MOROAMINGPROM">> => <<"false">>,
  <<"CON_MTROAMINGPROM">> => <<"false">>,
  <<"CON_NAME">> => <<"SMS Service">>,
  <<"CON_PMID">> => <<>>,
  <<"CON_PRICE">> => <<"8.00000000000000020000e-02">>,
  <<"CON_PRICEHG">> => <<"4.00000000000000010000e-02">>,
  <<"CON_PRICEINT">> => <<"8.00000000000000020000e-02">>,
  <<"CON_PRICEMOFN">> => <<>>,
  <<"CON_PROTOCOL">> => <<"UCP">>,
  <<"CON_PSCALL">> => <<"41754312835">>,
  <<"CON_RSID">> => <<"P0">>,
  <<"CON_SHORTID">> => <<>>,
  <<"CON_TARID">> => <<"h">>,
  <<"CON_THROUGHPUT">> => <<"1">>}.
Values =  [list_to_tuple([<<"ZK04ENGYDW">> | maps:values(NValue)])].
{executed, 1} = UpdStmt:exec_stmt(Values).
{cols, _} = ConJsonStmt:exec_stmt([{<<"ZK04ENGYDW">>}]).
{{rows, [[_,BinVal]]}, true}= ConJsonStmt:fetch_rows(1000).
DstVal =  maps:map(
      fun(_, I) when is_integer(I) -> integer_to_binary(I);
         (_, F) when is_float(F) -> float_to_binary(F);
         (_, null) -> <<>>;
         (_, A) when A == false; A == true -> atom_to_binary(A, utf8);
         (_, B) when is_binary(B) -> B
      end, maps:without([<<"AuditTime">>], imem_json:decode(BinVal, [return_maps]))).
lists:foldl(
        fun(K, M) ->
            L = maps:get(K, NValue, '$missing'),
            R = maps:get(K, DstVal , '$missing'),
            if L /= R ->
                   M#{K => #{local => L, remote => R}};
               true -> M
            end
        end, #{}, maps:keys(DstVal)).

Extected #{}. But this is not the case always

Closing oci_port should be done only in terminate

Duplicate implementation of terminate found in close have to be removed.

Close the port by deleting the child from supervisor which would in turn result in the terminate call (with trap_exit set to true).

Length param isn't respected in Stmt:lob(LobId, Offset, Length)

cc @acautin @stoch
Ref : https://docs.oracle.com/cd/B28359_01/appdev.111/b28395/oci17msc002.htm#i578721

oraub8 loblenc = 0;
checkerr(&r,
    OCILobRead2((OCISvcCtx*)_svchp, (OCIError*)_errhp, lob,
/* oraub8 *byte_amtp (IN/OUT)
IN - The number of bytes to read from the database. Used for BLOB and BFILE always. For CLOB and NCLOB, it is used only when char_amtp is zero.
OUT - The number of bytes read into the user buffer. */
       (oraub8*)&loblen,
/* oraub8 *char_amtp (IN/OUT)
IN - The maximum number of characters to read into the user buffer. Ignored for BLOB and BFILE.
OUT - The number of characters read into the user buffer. Undefined for BLOB and BFILE. */
       &loblenc,
       (oraub8)offset,
       (void*)buf,
       (oraub8)length,
       OCI_ONE_PIECE, (dvoid*)0, (OCICallbackLobRead2)0, (ub2)0, csfrm)
);
if(r.fn_ret != OCI_SUCCESS) {
    REMOTE_LOG(ERR, "failed OCILobRead2 for %p reason %s (%s)\n", lob, r.gerrbuf, _stmtstr);
    throw r;
} 

oraub8 loblenc = 0;
checkerr(&r, OCILobRead2((OCISvcCtx*)_svchp, (OCIError*)_errhp, lob, (oraub8*)&loblen, &loblenc, (oraub8)offset, (void*)buf, (oraub8)length , OCI_ONE_PIECE, (dvoid*)0, (OCICallbackLobRead2)0, (ub2)0, csfrm));
if(r.fn_ret != OCI_SUCCESS) {
REMOTE_LOG(ERR, "failed OCILobRead2 for %p reason %s (%s)\n", lob, r.gerrbuf, _stmtstr);
throw r;
}

Always full byte/char length is requested!

Error reading CLOB in logger_log

From console.

[error] [_DDRL_] {c_src/erloci_lib/ocistmt.cpp:rows:930} failed OCILobGetLength
 for 0x7fad0f8b59f8 row 1 column 13 reason [rows:928] Error - OCI_INVALID_HANDLE
 (select SCOTT.LOGGER_LOGS.*, SCOTT.LOGGER_LOGS.ROWID from SCOTT.LOGGER_LOGS)
[error] [_DDRL_] {dderl_fsm,1218} Error on fsm <0.5860.0> when State filling
 Message:  {0,<<"[rows:928] Error - OCI_INVALID_HANDLE\n">>}

Out sysdate parameter kills the connection.

OciPort = erloci:new([{logging, true}, {env, [{"NLS_LANG", "GERMAN_SWITZERLAND.AL32UTF8"}]}]).
OciSession = -------     Connection to database   --------.
SelectSysdate = <<"BEGIN :SQLT_DAT_OUT_RESULT := TO_DATE(SYSDATE); END;">>,
BoundStmt = OciSession:prep_sql(SelectSysdate).
SelectBinds = [{<<":SQLT_DAT_OUT_RESULT">>, out, 'SQLT_DAT'}].
ok = BoundStmt:bind_vars(SelectBinds).
f(R1).
R1 = [{<<0,0,0,0,0,0,0,0>>}].
BoundStmt:exec_stmt(R1).

Results in:

06.09.2016 08:59:32.721699 [error] [_OCI_] {c_src/erloci_lib/ocistmt.cpp,execute,780} Unsuported out variable type 12 (BEGIN :SQLT_DAT_OUT_RESULT := TO_DATE(SYSDATE); END;)
{error,{0,<<"[execute:779] unsupporetd type 12\n">>}}
{oci_logger,103} TCP closed
([email protected])27> {oci_logger,132} Terminating normal

Problem with binding vars

When i try insert some values to table, i have this error:

Assertion failed: ((*it).is_tuple() && (*it).length() == 3 && (*it)[0].is_binary() && (*it)[1].is_any_int() && (*it)[2].is_any_int()), function map_schema_to_bind_args, file c_src/erloci_drv/marshal.cpp, line 297.

My table: "CREATE TABLE \"schema_migrations\" (\"version\" NUMBER, \"inserted_at\" DATE)"

My insert:

"INSERT INTO \"schema_migrations\" (\"inserted_at\",\"version\") VALUES (:inserted_at, :version)"
[inserted_at: {{2016, 1, 6}, {14, 11, 39, 0}}, version: 0]
After mapping:
[{<<120, 116, 1, 6, 14, 11, 39>>, 0}]

Multiple row insert in single statement

insert all into erloci_test_1 (name) values ('test1') into erloci_test_1 (name) values ('test2') into erloci_test_1 (name) values ('test3') into erloci_test_1 (name) values ('test4') select * from dual

::{port_exit,{'SIGSEGV',core,"Segmentation Fault"}}

=ERROR REPORT==== 7-Sep-2014::09:58:07 ===
** Generic server <0.101.0> terminating
** Last message in was {#Port<0.29190>,{exit_status,139}}
** When Server state == {state,#Port<0.29190>,true,1,
{oci_logger,<0.102.0>},
{<<131,104,2,103,100,0,13,110,111,110,111,100,
101,64,110,111,104,111,115,116,0,0,0,104,0,0,
0,0,0,114,0,3,100,0,13,110,111,110,111,100,
101,64,110,111,104,111,115,116,0,0,3,71,143,
0,0,0,3,0,0,0,0>>,
6,140593674062192,140593271573424,[],1}}
** Reason for termination ==
** {port_exit,{'SIGSEGV',core,"Segmentation Fault"}}

query execute failure on SBS test installation

Problem processing command: error:function_clause
[{<<"query">>,[{<<"connection">>,<<"g2gDZAAIb2NpX3BvcnRnZAAhc2JzZ3VpQHZpbWFwZ2V0LXNic2gwMS5pdC5id25zLmNoAABaIwAAARECYgA6n4A=">>},{<<"qstr">>,<<"SELECT\r\n *\r\nFROM\r\n dba_users">>},{<<"conn_id">>,<<"133876732">>},{<<"binds">>,null}]}]
[{oci_adapter,process_log_binds,[undefined],[{file,"c:/Program Files (x86)/Jenkins/workspace/sbsgui/_build/default/lib/dderl/src/oci_adapter.erl"},{line,739}]},{oci_adapter,process_query,5,[{file,"c:/Program Files (x86)/Jenkins/workspace/sbsgui/_build/default/lib/dderl/src/oci_adapter.erl"},{line,676}]},{oci_adapter,process_cmd,6,[{file,"c:/Program Files (x86)/Jenkins/workspace/sbsgui/_build/default/lib/dderl/src/oci_adapter.erl"},{line,233}]},{dderl_session,spawn_process_call,8,[{file,"c:/Program Files (x86)/Jenkins/workspace/sbsgui/_build/default/lib/dderl/src/dderl_session.erl"},{line,645}]}]

@shamis can you please analyze the possible reason for this.

This is the installation:

image

One failed query can prevent future queries working

From K2InformaticsGmbH/dderl#517

Tested with:

OciPort = erloci:new([{logging, true}, {env, [{"NLS_LANG", "GERMAN_SWITZERLAND.AL32UTF8"}]}]).
OciSession = OciPort:get_session(<<"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=XXXXXXXX)(PORT=XXXXXXXX)))(CONNECT_DATA=(SERVICE_NAME=XE)))">>, <<"XXXXXXXX">>, <<"XXXXXXXX">>).
Select = <<"select SCOTT.NUMBER_LONG.*, SCOTT.NUMBER_LONG.ROWID from SCOTT.NUMBER_LONG">>,
Stmt = OciSession:prep_sql(Select).
Stmt:exec_stmt().

Produces the output:

    (sbsgui@127.0.0.1)3> OciPort = erloci:new([{logging, true}, {env, [{"NLS_LANG", "GERMAN_SWITZERLAND.AL32UTF8"}]}]).
    15.10.2018 14:25:23.992034 [debug] [_OCI_] {oci_logger,,71} ---- ERLOCI PORT PROCESS LOGGER ----
    15.10.2018 14:25:23.995507 [debug] [_OCI_] {oci_port,,292} DYLD_LIBRARY_PATH = .../Users/agustin/Documents/oracle/instantclient_11_2
    15.10.2018 14:25:23.995768 [debug] [_OCI_] {oci_port,,300} Extra Env :[{"NLS_LANG","GERMAN_SWITZERLAND.AL32UTF8"}]
    15.10.2018 14:25:23.995890 [debug] [_OCI_] {oci_port,,310} Executable "_build/default/lib/erloci/priv/ocierl"
    15.10.2018 14:25:23.995988 [debug] [_OCI_] {oci_port,,311} Options :[{packet,4},
            binary,exit_status,use_stdio,
            {args,["262144","true","54930"]},
            {env,[{"DYLD_LIBRARY_PATH",
                    "/Users/agustin/Documents/oracle/instantclient_11_2"},
                    {"NLS_LANG","GERMAN_SWITZERLAND.AL32UTF8"}]}]
    15.10.2018 14:25:23.996786 [debug] [_OCI_] {oci_port,,321} started log enabled new port:
    [{name,"_build/default/lib/erloci/priv/ocierl"},
    {links,[<0.28905.0>]},
    {id,9183},
    {connected,<0.28905.0>},
    {input,0},
    {output,19},
    {os_pid,57871}]
    15.10.2018 14:25:23.997011 [debug] [_OCI_] {oci_logger,,116} 15.10.2018 14:25:23.996967 Waiting for peer to connect on 54930
    15.10.2018 14:25:24.018012 [debug] [_OCI_] {oci_logger,,124} 15.10.2018 14:25:24.017937 Connection from 54931 to 54930
    15.10.2018 14:25:24.018248 [info] [_OCI_] {c_src/erloci_drv/erloci.cpp,main,83} [57871] Port process configs : erlang term max size 0x00040000 bytes, logging enabled, TCP port for logs 54930, NLS_LANG GERMAN_SWITZERLAND.AL32UTF
    {oci_port,<0.28905.0>}
    15.10.2018 14:25:24.018451 [debug] [_OCI_] {c_src/erloci_drv/threads.cpp,threads,39} Initializing Thread pool..
    (sbsgui@127.0.0.1)4> OciSession = OciPort:get_session(<<"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=XXXXXXXX)(PORT=XXXXXXXX)))(CONNECT_DATA=(SERVICE_NAME=XE)))">>, <<XXXXXXXX>>, <<XXXXXXXX>>).
    15.10.2018 14:25:24.034922 [info] [_OCI_] {c_src/erloci_lib/ocisession.cpp,config,69} OCI Initialize
    15.10.2018 14:25:24.089419 [info] [_OCI_] {c_src/erloci_drv/command.cpp,change_log_flag,54} Enabled logging..
    15.10.2018 14:25:24.090126 [info] [_OCI_] {oci_port,,429} Remote log_enabled
    15.10.2018 14:25:24.090441 [debug] [_OCI_] {oci_port,,369} no reply for log_enabled
    {oci_port,<0.28905.0>,140675075038352}
    15.10.2018 14:25:24.127040 [info] [_OCI_] {c_src/erloci_lib/ocisession.cpp,ocisession,128} got session 0x7ff179031338 (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.1.43)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=XE))) user scott
    (sbsgui@127.0.0.1)5> Select = <<"select SCOTT.NUMBER_LONG.*, SCOTT.NUMBER_LONG.ROWID from SCOTT.NUMBER_LONG">>,
    (sbsgui@127.0.0.1)5> Stmt = OciSession:prep_sql(Select).
    {oci_port,statement,<0.28905.0>,140675075038352,
            140675073984544}
    (sbsgui@127.0.0.1)6> Stmt:exec_stmt().
    15.10.2018 14:25:25.423975 [error] [_OCI_] {c_src/erloci_lib/ocistmt.cpp,execute,707} Unsupported column type 8
    {error,{0,<<"[execute:706] unsupporetd type 8\n">>}}
    15.10.2018 14:25:25.424772 [debug] [_OCI_] {c_src/erloci_drv/threads.cpp,~threads,85} Cleanup Thread pool..
    {oci_logger,108} TCP closed
    {oci_logger,137} Terminating normal
    (sbsgui@127.0.0.1)7> OciSession:prep_sql(Select).
    ** exception exit: {noproc,
                        {gen_server,call,
                            [<0.28905.0>,
                                {port_call,
                                    [4,140675075038352,
                                    <<"select SCOTT.NUMBER_LONG.*, SCOTT.NUMBER_LONG.ROWID from SCOTT.NUMBE"...>>]},
                                infinity]}}
        in function  gen_server:call/3 (gen_server.erl, line 214)
        in call from oci_port:prep_sql/2 (/Users/agustin/Documents/k2_informatics/sbsgui/_build/default/lib/erloci/src/oci_port.erl, line 139)
    (sbsgui@127.0.0.1)8> 14:26:03.259 [info] [_DDRL_] {dderl_session,159} session {<0.28862.0>,<<>>} idle for 90000 ms
    14:26:03.259 [info] [_DDRL_] {dderl_session,195} dderl_session {<0.28862.0>,<<>>} terminating, reason normal

exec_stmt blocking call.

We stumbled upon a problem when one of the tables was blocked by a non terminated transaction. The call to exec_stmt will never finish
and after login out of dderl ocierl.exe was hanging around even after restarting the service with the table locked (was not able to reproduce that
locally on os x).

I tried creating a table with only one column and then added rows 1 & 2:

OciPort = erloci:new([{logging, true}, {env, [{"NLS_LANG", "GERMAN_SWITZERLAND.AL32UTF8"}]}]).
OciSession = OciPort:get_session(<<"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=XX.XX.XXX.XXX)(PORT=XXXX)))(CONNECT_DATA=(SERVICE_NAME=XE)))">>,
<<"user">>, <<"pass">>).
CreateTable = <<"create table test (COL1 int)">>.
CreateStmt = OciSession:prep_sql(CreateTable).
CreateStmt:exec_stmt().

Then in 2 separated vms executed:

DeleteRow = <<"delete from test where COL1 = :SOMEVAR">>.
DeleteStmt = OciSession:prep_sql(DeleteRow).
DeleteStmt:bind_vars([{<<":SOMEVAR">>, 'SQLT_STR'}]).
DeleteStmt:exec_stmt([{<<"2">>}],0).

On the first one I got:

([email protected])43> DeleteStmt:exec_stmt([{<<"2">>}],0).
23.11.2016 19:44:30.520476 [debug] [_OCI_] {c_src/erloci_drv/command.cpp,exec_stmt,525} Bounds 
{rowids,[<<"AAAU99AABAAALJxAAA">>]}

But the second one was a blocking call, maybe this is the expected behavior when a transaction can't be completed ?

SQL Procedure Binding Support for DATE OUT Parameters (Type 12)

Queries like this one should be supported in DDerl:

begin pkg_mtrac_sms.scan_index(:SQLT_STR_TABLE, :SQLT_DAT_START_DATE, :SQLT_DAT_END_DATE, :SQLT_STR_SENDER, :SQLT_STR_RECEIVER, :SQLT_STR_SHORTID, :SQLT_STR_GENERATED, :SQLT_VNU_ROWLIMIT, :SQLT_DAT_OUT_START_DATE, :SQLT_DAT_OUT_END_DATE, :SQLT_VNU_OUT_COUNT); end;

This means that we need to support DATE out parameter binding.

error code in my charset: ZHS16GBK

I can't got binary with right charset:

11> f(OciPort), OciPort = erloci:new([{logging, true},{env, [{"NLS_LANG","SIMPLIFIED CHINESE_CHINA.ZHS16GBK"}]}]).
12> f(OciSession), OciSession = OciPort:get_session(Tns, User, Pass).
13> f(SelectStmt), SelectStmt = OciSession:prep_sql(SelectSql).
14> SelectStmt:exec_stmt().
{cols,[{<<"SUPPLYNAME">>,'SQLT_CHR',50,0,0}]}
15> SelectStmt:fetch_rows(5).                                                                                     
{{rows,[[<<"¹ã¶«Ê¡¶«Ý¸¹úÒ©¼¯ÍÅÈʼÃÌÃÒ©ÒµÓÐÏÞ¹«Ë¾">>]]},true

In fact, I run the unit test for my oracle:

fun() ->
      application:start(erloci),
      OciPort = erloci:new([{logging, true}, {env, [{"NLS_LANG", "SIMPLIFIED CHINESE_CHINA.ZHS16GBK"}]}]),
...

and got follow error:

erloci_test: db_test_...*failed*
in function erloci_test:'-timestamp_interval_datatypes/1-fun-11-'/2 (test/erloci_test.erl, line 865)
in call from erloci_test:timestamp_interval_datatypes/1 (test/erloci_test.erl, line 858)
**error:{assertEqual_failed,[{module,erloci_test},
                     {line,865},
                     {expression,"SelectStmt : exec_stmt ( )"},
                     {expected,{cols,[{<<"NAME">>,'SQLT_CHR',30,0,0},
                                      {<<"DAT">>,'SQLT_DAT',7,0,0},
                                      {<<"TS">>,'SQLT_TIMESTAMP',11,0,6},
                                      {<<"TSTZ">>,'SQLT_TIMESTAMP_TZ',13,0,6},
                                      {<<"TSLTZ">>,'SQLT_TIMESTAMP_LTZ',11,0,...},
                                      {<<"IYM">>,'SQLT_INTERVAL_YM',5,...},
                                      {<<"IDS">>,'SQLT_INTERVAL_DS',...}]}},
                     {value,{cols,[{<<"NAME">>,'SQLT_CHR',60,0,0},
                                   {<<"DAT">>,'SQLT_DAT',7,0,0},
                                   {<<"TS">>,'SQLT_TIMESTAMP',11,0,6},
                                   {<<"TSTZ">>,'SQLT_TIMESTAMP_TZ',13,0,...},
                                   {<<"TSLTZ">>,'SQLT_TIMESTAMP_LTZ',11,...},
                                   {<<"IYM">>,'SQLT_INTERVAL_YM',...},
                                   {<<...>>,...}]}}]}



=INFO REPORT==== 19-Apr-2015::00:56:19 ===
    application: erloci
    exited: stopped
    type: temporary
=======================================================
  Failed: 2.  Skipped: 0.  Passed: 53.
Cover analysis: /Users/homeway/erlang/research/erloci/.eunit/index.html
ERROR: One or more eunit tests failed.
ERROR: eunit failed while processing /Users/homeway/erlang/research/erloci: rebar_abort

008741 Debugging API for erloci port implementation

Operational statistics should be accessible in order to check / debug proper working conditions and possibly memory leaks:

  • Session Count
  • Statement Count
  • Allocated Buffer Sizes
  • Last Session Activity TS

Ideally, we would be able to dump internal state snapshot when needed and analyze it offline (in some open source analyzer tool or self-woven erlang tool).

If this is too difficult, compiling for debug and starting a pool or single driver in debug mode should at least be possible.

Comments so far:

Native programs like ocierl.exe or erlang VM (erl.exe) doesn’t let inspection for memory leakage or reading of any other internal process state info from outside. So at the moment we can’t debug ocierl.exe for memory leak.
However we can start ocierl.exe differently (compiled with debug) with some Microsoft memory analyzer tool (like http://valgrind.org/ in linux) and try to make it work and interpret the data. Not sure what is available and will work for erloci – requires some trial and error.
If not, please consider creating one which gives insight into the resource consumption per session and statement (together with last access timestamp if possible).
One lead to this direction would be https://msdn.microsoft.com/en-us/library/x98tx3cf.aspx a good approach to detect memory leaks. I am not sure however it can be per OCI session/statement (not even sure I can be per thread). I can’t confirm what will be possible until I try different options.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.