Error: Unknown Error executing query #106

Closed
rdev5 opened this Issue Dec 10, 2013 · 21 comments

Projects

None yet

8 participants

@rdev5
rdev5 commented Dec 10, 2013
Oracle.connect = function(callback) {
   oracle_driver.connect(connectData, function(err, connection) {
      if(err) {
         console.log(err);
      } else {
         callback(err, connection);
      }
      connection.close();
   });
}

Oracle.query = function(query, callback) {
   Oracle.connect(function(err, connection) {
      connection.execute(query, [], function(err, results) {
         if (err) {
            console.log(err);
            callback(err, results);
         } else {
            callback(err, results);
         }
      });
   });
}

Query is very simple and I've already verified it is valid. However, I'm getting an [Error: Unknown Error] and am using the 64-bit version of the instantclient on Mac OS X. Should I switch to 32-bit?

Also, if I try to inspect the connection object, it returns {} but no errors reported. I am also using the connectData object, passing the required parameters including hostname, username, database, and password.

@rdev5
rdev5 commented Dec 10, 2013

Went to double check. 32-bit won't link on my arch so I ensured both instantclient and the sdk were 64-bit after noticing I accidentally mixed the two. Still getting the same "Unknown Error" and apparently am neither connected nor able to execute queries.

@misterfitz

Same issue here, using OSX Mavericks 10.9 & either 32-bit or 64-bit

@kontrafiktion

Which version of InstantClient?

@misterfitz

Tried 11.2.0.3 32-bit and 12.1.0.1.0 32 and 64-bit. No luck :/

@rdev5
rdev5 commented Dec 12, 2013

I'm using the latest straight from the Oracle site as of the day of this posting.

@misterfitz

Issue resolved, total operator error, wrong server IP/name address. I am using Oracle 11.2.0.3.0 x64 on Mac OSX 10.9 Mavericks.

Thanks for checking back.

@rdev5
rdev5 commented Dec 12, 2013

@dooleyburger It appears that the test instance of our Oracle database is not set up to allow connections but trying another instance worked just fine so I'm going to chalk this one up to a configuration issue.

Still, though, the error thrown here needs to be a little more insightful. Error: Unknown Error is not only vague, but also implies that there is some error handling taking place within the module that is replacing the underlying caught error with its own set of known errors.

It appears that I am directly referring to these lines: https://github.com/joeferner/node-oracle/blob/master/src/connection.cpp#L402-L482

Does the try catch need to be this all-encompassing? Would recommend at least checking return values to see if NodeOracleException needs to be thrown sooner.

Did a node-gyp rebuild and removed the catch(..) to reveal that this was being thrown:

libc++abi.dylib: terminating with uncaught exception of type oracle::occi::SQLException: ORA-00942: table or view does not exist

@rdev5
rdev5 commented Dec 13, 2013

To reiterate my question, why is catch(oracle::occi::SQLException &ex) not catching uncaught exception of type oracle::occi::SQLException: ORA-00942: table or view does not exist and falling through to catch (...)?

@kontrafiktion

There is an open issue (#94), which talks about exception handling and node.js. I am not sure if I understand it, but to me that sounds like node.js (and V8) are compiled without exception handling and if some code uses exceptions it may be in "undefined" territory

@raztus
Collaborator
raztus commented Feb 26, 2014

As a point of interest, this issue does not occur on Linux where the exception is properly caught in the catch(oracle::occi::SQLException &ex) block.

I can confirm this issue on OS X 10.9 with 64-bit InstantClient 11.2.0.3.0, and am investigating it now (though I'm admittedly not an expert in this area.)

@raztus
Collaborator
raztus commented Feb 26, 2014

Well, I gave this my best shot. I tried building with true g++-4.9 on OS X (Xcode comes with clang, which gyp leverages by default) by setting the compiler as described in nodejs/node-gyp#63, tried explicitly setting -fexceptions (gcc) and -fcxx-exceptions (clang), to no avail. I learned that these had to be set in the OTHER_CFLAGS block in "binding.gyp" to work (simply putting them in "cflags" didn't work):

  "xcode_settings": {
    "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
    'OTHER_CFLAGS': [
      '-fexceptions',
      '-fcxx-exceptions'
    ]
  }

See https://gist.github.com/TooTallNate/1590684 for comments on this.

I also tried building with C++11 enabled and using std::current_exception(); inside the catch (...) { block, in hopes that it would allow me to inspect the exception being thrown, then learned that that's not the purpose of current_exception().

Finally I tried to catch various forms of the SQLException, with no luck:

  } catch(oracle::occi::SQLException &ex) {
    baton->error = new string(ex.getMessage());
  } catch(oracle::occi::SQLException* ex) {
    baton->error = new string(ex->getMessage());
  } catch(oracle::occi::SQLException ex) {
    baton->error = new string(ex.getMessage());

I don't understand what the difference between the Linux and OS X environment is that would cause this. @bjouhier Any clues here?

@bjouhier

This is weird and I did not have time to investigate. Your first catch line (oracle::occi::SQLException &ex) should be sufficient.

The problem is, as TooTallNate explained it, that node is compiled with C++ exceptions turned off. Then all sorts of strange things may happen if exceptions are thrown across scopes that call node or v8 APIs. And the effect seems to depend heavily on the OS and compiler. I observed this when I upgraded gcc to 4.7.3 on my mac. I did not have the problem before and with the new compiler exceptions started to crash the process or put it into an infinite loop.

In one of my commits (0bc878f) I changed the code to propagate exceptions by catching them at the low level and setting baton->error instead of using throw. This has dramatically improved the situation because I'm now getting most (I'm not sure it's all) errors propagated correctly to the JS code.

But there is still some code in which SQLExceptions are propagated across scopes. A typical example is Connection::ExecuteStatement where exceptions thrown inside a loop are caught outside the loop. To be on the safe side, we should rewrite this code to have the try/catch around the occi calls inside the loop and use another mechanism than exceptions (a goto or an additional variable) to interrupt the loop and report the exception to the higher level.

So there is still some work to do to ensure that exceptions are caught as close as possible to the occi calls.

Q: is your try/catch directly around a single occi call, or is it around a larger piece of code that contains occi calls, like in Connection::ExecuteStatement?

@bjouhier

@raztus I just did a grep catch on the code and there are not that many places that need work. The main one is Connection::ExecuteStatement. I can do another pass to refactor the remaining spots.

@raztus
Collaborator
raztus commented Feb 27, 2014

The code I was referring to was Connection::ExecuteStatement, which in my case would fail at int status = stmt->execute(); (https://github.com/joeferner/node-oracle/blob/aa46f36aff7ab3d7d1791b722964dfe53e8b63dd/src/connection.cpp#L465)

I am curious now to attempt to build node with exceptions enabled. I'll try that soon.

@bjouhier

Did you try to move the catch clause just after the stmt->execute(); line (with another try just below)?

Compiling node with exception enabled is an interesting experiment but this is not a fix. The driver should work with regular node.

@raztus
Collaborator
raztus commented Mar 8, 2014

I've verified that this happens anywhere we are trying to catch an occi::SQLException (e.g., in EIO_Connect if you pass in a bad connection string: https://github.com/joeferner/node-oracle/blob/aa46f36aff7ab3d7d1791b722964dfe53e8b63dd/src/oracle_bindings.cpp#L129). This further solidified my guess that exception handling is not being turned on by the compiler.

I was finally able to get it to work, with clang only, by adding the following to "binding.gyp":

      "xcode_settings": {
          ...
          "GCC_ENABLE_CPP_RTTI": "YES"
       }

This prevents the -fno-rtti flag from being passed to clang. It's unclear to me what the performance implications of using RTTI are, but the benefit of having exception information on OS X is probably greater. (See: http://stackoverflow.com/questions/579887/how-expensive-is-rtti)

I've also verified that having that flag in binding.gyp does remove the -fno-rtti flag when using g++-4.9, but even still exceptions with that compiler are not handled (grr).

@bjouhier @joeferner Any thoughts about whether this flag should be included for OS X by default?

P.S. It does appear that one other author uses this in various libraries: https://github.com/mapnik/node-mapnik/blob/master/binding.gyp

@raztus
Collaborator
raztus commented Mar 8, 2014

Furthermore, I don't understand why on Linux (Ubuntu 12.04) using g++ 4.6.3, I do see -fno-rtti in the compiler output, and yet I also do get exceptions. I wonder what's different on OS X that RTTI is required for exceptions.

@RobertZito

rdev if you do not mind me asking, I have been attempting to put my connection in a callback for reuse but have been unlucky, so as I learn my way around what is oracle_driver in your code? I tested your code and get oracle_driver undefined.

@raztus raztus added a commit to raztus/node-oracle that referenced this issue Mar 24, 2014
@raztus raztus Enable RTTI on OS X to fix exception handling (gh issue #106) 55dd6cb
@raztus
Collaborator
raztus commented Mar 24, 2014

I have gone ahead and pushed this change to enable RTTI by default on OS X in 55dd6cb. Please let me know if you don't feel like this is the right solution.

@raztus raztus closed this Mar 24, 2014
@fr-nk
fr-nk commented Sep 5, 2014

I've the same error I can do any ddl, dml like this

connection.execute("create table test(a number)",

that works.

not select * from test

@andrewschools

I'm receiving the same issue on Windows 7 x64 ( [Error: Unknown Error] ). I have confirmed the select and database connection parameters are correct and working outside of this plugin. I have Python 2.7 installed along with the Windows SDK 7.1, instantclient-sdk-windows.x64-12.1.0.2.0, instantclient-basic-windows.x64-12.1.0.2.0, Visual Studio 2013 Express. I am able to run the following command:

npm install oracle --python=python2.7

Even though I get some warnings, the code is generated.

C:\Users\a551272\node_modules\oracle>node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin....\node_modules\node-gyp\bin\node-gyp.js" reb
uild
Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
connection.cpp
oracle_bindings.cpp
executeBaton.cpp
reader.cpp
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc (..\src\connection.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc (..\src\reader.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc (..\src\oracle_bindings.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc (..\src\executeBaton.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
..\src\oracle_bindings.cpp(103): warning C4244: '=' : conversion from 'double' to 'uint32_t', possible loss of data [C:\Users\a551272\node_modules\or
acle\build\oracle_bindings.vcxproj]
..\src\reader.cpp(57): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules\oracle
\build\oracle_bindings.vcxproj]
..\src\connection.cpp(182): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules\o
racle\build\oracle_bindings.vcxproj]
..\src\connection.cpp(192): warning C4101: 'ex' : unreferenced local variable [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
..\src\oracle_bindings.cpp(169): warning C4244: '=' : conversion from 'double' to 'uint32_t', possible loss of data [C:\Users\a551272\node_modules\or
acle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(91): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(92): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(93): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(94): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(95): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(96): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\executeBaton.cpp(97): warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules
oracle\build\oracle_bindings.vcxproj]
..\src\connection.cpp(590): warning C4244: '=' : conversion from 'double' to 'unsigned int', possible loss of data [C:\Users\a551272\node_modules\ora
cle\build\oracle_bindings.vcxproj]
..\src\connection.cpp(667): warning C4267: 'argument' : conversion from 'size_t' to 'unsigned int', possible loss of data [C:\Users\a551272\node_modu
les\oracle\build\oracle_bindings.vcxproj]
..\src\connection.cpp(672): warning C4267: 'argument' : conversion from 'size_t' to 'unsigned int', possible loss of data [C:\Users\a551272\node_modu
les\oracle\build\oracle_bindings.vcxproj]
..\src\connection.cpp(719): warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data [C:\Users\a551272\node_modules\oracl
e\build\oracle_bindings.vcxproj]
..\src\connection.cpp(801): warning C4267: 'argument' : conversion from 'size_t' to 'unsigned int', possible loss of data [C:\Users\a551272\node_modu
les\oracle\build\oracle_bindings.vcxproj]
..\src\connection.cpp(806): warning C4267: 'argument' : conversion from 'size_t' to 'unsigned int', possible loss of data [C:\Users\a551272\node_modu
les\oracle\build\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::Object v8::Persis
tentv8::Object::New(v8::Handlev8::Object)' (..\src\oracle_bindings.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::FunctionTemplate
v8::Persistentv8::FunctionTemplate::New(v8::Handlev8::FunctionTemplate)' (..\src\oracle_bindings.cpp) [C:\Users\a551272\node_modules\oracle\build
\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::Object v8::Persis
tentv8::Object::New(v8::Handlev8::Object)' (..\src\reader.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::FunctionTemplate
v8::Persistentv8::FunctionTemplate::New(v8::Handlev8::FunctionTemplate)' (..\src\reader.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_b
indings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::Object v8::Persis
tentv8::Object::New(v8::Handlev8::Object)' (..\src\executeBaton.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
statement.cpp
outParam.cpp
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::Object v8::Persis
tentv8::Object::New(v8::Handlev8::Object)' (..\src\connection.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::FunctionTemplate
v8::Persistentv8::FunctionTemplate::New(v8::Handlev8::FunctionTemplate)' (..\src\connection.cpp) [C:\Users\a551272\node_modules\oracle\build\orac
le_bindings.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc (..\src\statement.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not
enabled. Specify /EHsc (..\src\outParam.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
..\src\outParam.cpp(30): warning C4244: '=' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules\oracle\build\or
acle_bindings.vcxproj]
..\src\outParam.cpp(37): warning C4244: '=' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules\oracle\build\or
acle_bindings.vcxproj]
..\src\outParam.cpp(44): warning C4244: '=' : conversion from 'double' to 'int', possible loss of data [C:\Users\a551272\node_modules\oracle\build\or
acle_bindings.vcxproj]
..\src\outParam.cpp(52): warning C4244: '=' : conversion from 'double' to 'float', possible loss of data [C:\Users\a551272\node_modules\oracle\build
oracle_bindings.vcxproj]
..\src\outParam.cpp(52): warning C4244: '=' : conversion from 'int' to 'float', possible loss of data [C:\Users\a551272\node_modules\oracle\build\ora
cle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::Object v8::Persis
tentv8::Object::New(v8::Handlev8::Object)' (..\src\statement.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::FunctionTemplate
v8::Persistentv8::FunctionTemplate::New(v8::Handlev8::FunctionTemplate)' (..\src\statement.cpp) [C:\Users\a551272\node_modules\oracle\build\oracl
e_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::Object v8::Persis
tentv8::Object::New(v8::Handlev8::Object)' (..\src\outParam.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle_bindings.vcxproj]
C:\Users\a551272.node-gyp\0.10.32\deps\v8\include\v8.h(184): warning C4506: no definition for inline function 'v8::Persistentv8::FunctionTemplate
v8::Persistentv8::FunctionTemplate::New(v8::Handlev8::FunctionTemplate)' (..\src\outParam.cpp) [C:\Users\a551272\node_modules\oracle\build\oracle
_bindings.vcxproj]
Creating library C:\Users\a551272\node_modules\oracle\build\Release\oracle_bindings.lib and object C:\Users\a551272\node_modules\oracle\build\Re
lease\oracle_bindings.exp
Generating code
Finished generating code
oracle_bindings.vcxproj -> C:\Users\a551272\node_modules\oracle\build\Release\oracle_bindings.node
oracle@0.3.7 node_modules\oracle

I am using the following Node.JS Code:

var oracle = require('oracle');

var connectData = {
    hostname: "",
    port: 1521,
    database: "", // System ID (SID)
    user: "",
    password: ""
}

oracle.connect(connectData, function(err, connection) {
    if (err) { console.log("Error connecting to db:", err); return; }
    connection.execute("SELECT owner FROM dba_tables", [], function(err, results) {
        if (err) { console.log("Error executing query:", err); return false; }
        console.log(results);
        connection.close(); // call only when query is finished executing
    });
});

The code exits on

if (err) { console.log("Error executing query:", err); return false; }

With [Error: Unknown Error]

Any help would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment