void MetadataNode::InjectPrototype(Local<Object>& target, Local<Object>& implementationObject)
{
	auto isolate = Isolate::GetCurrent();

	implementationObject->SetAccessor(ConvertToV8String("super"), SuperAccessorGetterCallback, nullptr, implementationObject);
	implementationObject->SetPrototype(target->GetPrototype());
	target->SetPrototype(implementationObject);
}
Пример #2
0
Local<Object> ODBC::GetSQLError (SQLSMALLINT handleType, SQLHANDLE handle, char* message) {
  HandleScope scope;
  
  DEBUG_PRINTF("ODBC::GetSQLError : handleType=%i, handle=%p\n", handleType, handle);
  
  Local<Object> objError = Object::New();
  
  SQLINTEGER i = 0;
  SQLINTEGER native;
  
  SQLSMALLINT len;
  SQLINTEGER numfields;
  SQLRETURN ret;
  char errorSQLState[14];
  char errorMessage[512];

  SQLGetDiagField(
    handleType,
    handle,
    1,
    SQL_DIAG_NUMBER,
    &numfields,
    SQL_IS_INTEGER,
    &len);
  
  for (i = 0; i < numfields; i++){
    DEBUG_PRINTF("ODBC::GetSQLError : calling SQLGetDiagRec; i=%i, numfields=%i\n", i, numfields);
    
    ret = SQLGetDiagRec(
      handleType, 
      handle,
      i + 1, 
      (SQLTCHAR *) errorSQLState,
      &native,
      (SQLTCHAR *) errorMessage,
      sizeof(errorMessage),
      &len);
    
    DEBUG_PRINTF("ODBC::GetSQLError : after SQLGetDiagRec; i=%i\n", i);

    if (SQL_SUCCEEDED(ret)) {
      DEBUG_PRINTF("ODBC::GetSQLError : errorMessage=%s, errorSQLState=%s\n", errorMessage, errorSQLState);
      
      objError->Set(String::New("error"), String::New(message));
#ifdef UNICODE
      objError->SetPrototype(Exception::Error(String::New((uint16_t *) errorMessage)));
      objError->Set(String::New("message"), String::New((uint16_t *) errorMessage));
      objError->Set(String::New("state"), String::New((uint16_t *) errorSQLState));
#else
      objError->SetPrototype(Exception::Error(String::New(errorMessage)));
      objError->Set(String::New("message"), String::New(errorMessage));
      objError->Set(String::New("state"), String::New(errorSQLState));
#endif
    }
  }
  
  return scope.Close(objError);
}
void MetadataNode::InterfaceConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
	SET_PROFILER_FRAME();

	auto isolate = info.GetIsolate();
	auto thiz = info.This();
	auto node = reinterpret_cast<MetadataNode*>(info.Data().As<External>()->Value());

	Local<Object> implementationObject;
	Local<String> v8ExtendName;
	string extendLocation;
	bool extendLocationFound = GetExtendLocation(extendLocation);
	if (info.Length() == 1)
	{
		if (!extendLocationFound)
		{
			ASSERT_FAIL("Invalid extend() call. No name specified for extend. Location: %s", extendLocation.c_str());
		}

		ASSERT_MESSAGE(info[0]->IsObject(), "Invalid extend() call. No implementation object specified. Location: %s", extendLocation.c_str());
		implementationObject = info[0]->ToObject();
	}
	else if (info.Length() == 2)
	{
		ASSERT_MESSAGE(info[0]->IsString(), "Invalid extend() call. No name for extend specified. Location: %s", extendLocation.c_str());
		ASSERT_MESSAGE(info[1]->IsObject(), "Invalid extend() call. Named extend should be called with second object parameter containing overridden methods. Location: %s", extendLocation.c_str());

		DEBUG_WRITE("InterfaceConstructorCallback: getting extend name");
		v8ExtendName = info[0]->ToString();
		implementationObject = info[1]->ToObject();
	}
	else
	{
		ASSERT_FAIL("Invalid extend() call. Location: %s", extendLocation.c_str());
	}

	auto className = node->m_implType;
	auto extendName = ConvertToString(v8ExtendName);
	auto extendNameAndLocation = extendLocation + extendName;
	SetInstanceMetadata(isolate, implementationObject, node);

	//@@@ Refactor
	thiz->SetInternalField(static_cast<int>(ObjectManager::MetadataNodeKeys::CallSuper), True(isolate));

	string fullClassName = CreateFullClassName(className, extendNameAndLocation);

	implementationObject->SetPrototype(thiz->GetPrototype());
	thiz->SetPrototype(implementationObject);
	thiz->SetHiddenValue(ConvertToV8String("t::implObj"), implementationObject);

	ArgsWrapper argWrapper(info, ArgType::Interface, Local<Object>());

	auto success = NativeScriptRuntime::RegisterInstance(thiz, fullClassName, argWrapper, implementationObject, true);
}
Пример #4
0
FunctionTemplate::FunctionTemplate() :
  Template(&gFunctionTemplateClass)
{
  PrivateData* data = cx()->new_<PrivateData>();
  JS_SetPrivate(cx(), JSVAL_TO_OBJECT(mVal), data);

  Handle<ObjectTemplate> protoTemplate = ObjectTemplate::New();
  Set("prototype", protoTemplate);
  // Instance template
  Local<ObjectTemplate> instanceTemplate = ObjectTemplate::New();
  instanceTemplate->SetPrototype(protoTemplate);

  data->instanceTemplate = instanceTemplate;
  data->callback = NULL;
}
Local<Object> MetadataNode::CreateExtendedJSWrapper(Isolate *isolate, const string& proxyClassName)
{
	Local<Object> extInstance;

	auto cacheData = GetCachedExtendedClassData(isolate, proxyClassName);
	if (cacheData.node != nullptr)
	{
		extInstance = s_objectManager->GetEmptyObject(isolate);
		extInstance->SetInternalField(static_cast<int>(ObjectManager::MetadataNodeKeys::CallSuper), True(isolate));
		auto extdCtorFunc = Local<Function>::New(isolate, *cacheData.extendedCtorFunction);
		extInstance->SetPrototype(extdCtorFunc->Get(ConvertToV8String("prototype")));

		SetInstanceMetadata(isolate, extInstance, cacheData.node);
	}

	return extInstance;
}
Local<Object> MetadataNode::CreateJSWrapper(Isolate *isolate)
{
	Local<Object> obj;

	if (m_isArray)
	{
		obj = CreateArrayWrapper(isolate);
	}
	else
	{
		auto ctorFunc = GetConstructorFunction(isolate);

		//obj = Object::New(isolate);
		obj = s_objectManager->GetEmptyObject(isolate);
		obj->Set(ConvertToV8String("constructor"), ctorFunc);
		obj->SetPrototype(ctorFunc->Get(ConvertToV8String("prototype")));
		SetInstanceMetadata(isolate, obj, this);
	}

	return obj;
}
void MetadataNode::ExtendCallMethodHandler(const v8::FunctionCallbackInfo<v8::Value>& info)
{
	if (info.IsConstructCall())
	{
		string exMsg("Cannot call 'extend' as constructor");
		ExceptionUtil::GetInstance()->ThrowExceptionToJs(exMsg);
		return;
	}

	SET_PROFILER_FRAME();

	Local<Object> implementationObject;
	Local<String> extendName;
	string extendLocation;
	auto validArgs = ValidateExtendArguments(info, extendLocation, extendName, implementationObject);

	if (!validArgs)
		return;

	auto node = reinterpret_cast<MetadataNode*>(info.Data().As<External>()->Value());

	DEBUG_WRITE("ExtendsCallMethodHandler: called with %s", ConvertToString(extendName).c_str());

	string extendNameAndLocation = extendLocation + ConvertToString(extendName);
	auto fullClassName = TNS_PREFIX + CreateFullClassName(node->m_name, extendNameAndLocation);


	//
	//resolve class (pre-generated or generated runtime from dex generator)
	jclass resolvedClass = NativeScriptRuntime::ResolveClass(fullClassName, implementationObject); //resolve class returns GlobalRef
	std::string generatedFullClassName = s_objectManager->GetClassName(resolvedClass);
	//

	auto fullExtendedName = generatedFullClassName;
	DEBUG_WRITE("ExtendsCallMethodHandler: extend full name %s", fullClassName.c_str());

	auto isolate = info.GetIsolate();
	auto cachedData = GetCachedExtendedClassData(isolate, fullExtendedName);
	if (cachedData.extendedCtorFunction != nullptr)
	{
		auto cachedExtendedCtorFunc = Local<Function>::New(isolate, *cachedData.extendedCtorFunction);
		info.GetReturnValue().Set(cachedExtendedCtorFunc);
		return;
	}

	auto implementationObjectPropertyName = V8StringConstants::GetClassImplementationObject();
	//reuse validation - checks that implementationObject is not reused for different classes
	auto implementationObjectProperty = implementationObject->GetHiddenValue(implementationObjectPropertyName).As<String>();
	if (implementationObjectProperty.IsEmpty())
	{
		//mark the implementationObject as such and set a pointer to it's class node inside it for reuse validation later
		implementationObject->SetHiddenValue(implementationObjectPropertyName, String::NewFromUtf8(isolate, fullExtendedName.c_str()));
	}
	else
	{
		string usedClassName = ConvertToString(implementationObjectProperty);
		stringstream s;
		s << "This object is used to extend another class '" << usedClassName << "'";
		ExceptionUtil::GetInstance()->ThrowExceptionToJs(s.str());
		return;
	}

	auto baseClassCtorFunc = node->GetConstructorFunction(isolate);
	auto extendData = External::New(isolate, new ExtendedClassData(node, extendNameAndLocation, implementationObject, fullExtendedName));
	auto extendFuncTemplate = FunctionTemplate::New(isolate, ExtendedClassConstructorCallback, extendData);
	extendFuncTemplate->InstanceTemplate()->SetInternalFieldCount(static_cast<int>(ObjectManager::MetadataNodeKeys::END));

	auto extendFunc = extendFuncTemplate->GetFunction();
	auto prototypeName = ConvertToV8String("prototype");
	implementationObject->SetPrototype(baseClassCtorFunc->Get(prototypeName));
	implementationObject->SetAccessor(ConvertToV8String("super"), SuperAccessorGetterCallback, nullptr, implementationObject);

	auto extendFuncPrototype = extendFunc->Get(prototypeName).As<Object>();
	auto p = extendFuncPrototype->GetPrototype();
	extendFuncPrototype->SetPrototype(implementationObject);
	extendFunc->SetPrototype(baseClassCtorFunc);


	SetClassAccessor(extendFunc);
	SetTypeMetadata(isolate, extendFunc, new TypeMetadata(fullExtendedName));
	info.GetReturnValue().Set(extendFunc);

	s_name2NodeCache.insert(make_pair(fullExtendedName, node));

	ExtendedClassCacheData cacheData(extendFunc, fullExtendedName, node);
	s_extendedCtorFuncCache.insert(make_pair(fullExtendedName, cacheData));
}
Пример #8
0
Handle<Value> ODBC::GetColumnValue( SQLHSTMT hStmt, Column column, 
                                        uint16_t* buffer, int bufferLength) {
  HandleScope scope;
  SQLLEN len = 0;

  //reset the buffer
  buffer[0] = '\0';

  //TODO: SQLGetData can supposedly return multiple chunks, need to do this to 
  //retrieve large fields
  int ret; 
  
  switch ((int) column.type) {
    case SQL_INTEGER : 
    case SQL_SMALLINT :
    case SQL_TINYINT : {
        long value;
        
        ret = SQLGetData(
          hStmt, 
          column.index, 
          SQL_C_SLONG,
          &value, 
          sizeof(value), 
          &len);
        
        DEBUG_PRINTF("ODBC::GetColumnValue - Integer: index=%i name=%s type=%i len=%i ret=%i\n", 
                    column.index, column.name, column.type, len, ret);
        
        if (len == SQL_NULL_DATA) {
          return scope.Close(Null());
          //return Null();
        }
        else {
          return scope.Close(Integer::New(value));
          //return Integer::New(value);
        }
      }
      break;
    case SQL_NUMERIC :
    case SQL_DECIMAL :
    case SQL_BIGINT :
    case SQL_FLOAT :
    case SQL_REAL :
    case SQL_DOUBLE : {
        double value;
        
        ret = SQLGetData(
          hStmt, 
          column.index, 
          SQL_C_DOUBLE,
          &value, 
          sizeof(value), 
          &len);
        
         DEBUG_PRINTF("ODBC::GetColumnValue - Number: index=%i name=%s type=%i len=%i ret=%i val=%f\n", 
                    column.index, column.name, column.type, len, ret, value);
        
        if(len == SQL_NULL_DATA) {
          return scope.Close(Null());
          //return Null();
        }
        else {
          return scope.Close(Number::New(value));
          //return Number::New(value);
        }
      }
      break;
    case SQL_DATETIME :
    case SQL_TIMESTAMP : {
      //I am not sure if this is locale-safe or cross database safe, but it 
      //works for me on MSSQL
#ifdef _WIN32
      struct tm timeInfo = {};

      ret = SQLGetData(
        hStmt, 
        column.index, 
        SQL_C_CHAR,
        (char *) buffer, 
        bufferLength, 
        &len);

      DEBUG_PRINTF("ODBC::GetColumnValue - W32 Timestamp: index=%i name=%s type=%i len=%i\n", 
                    column.index, column.name, column.type, len);

      if(len == SQL_NULL_DATA) {
        return scope.Close(Null());
        //return Null();
      }
      else {
        strptime((char *) buffer, "%Y-%m-%d %H:%M:%S", &timeInfo);

        //a negative value means that mktime() should use timezone information 
        //and system databases to attempt to determine whether DST is in effect 
        //at the specified time.
        timeInfo.tm_isdst = -1;
          
        //return Date::New((double(mktime(&timeInfo)) * 1000));
        return scope.Close(Date::New((double(mktime(&timeInfo)) * 1000)));
      }
#else
      struct tm timeInfo = { 
        tm_sec : 0
        , tm_min : 0
        , tm_hour : 0
        , tm_mday : 0
        , tm_mon : 0
        , tm_year : 0
        , tm_wday : 0
        , tm_yday : 0
        , tm_isdst : 0
        , tm_gmtoff : 0
        , tm_zone : 0
      };

      SQL_TIMESTAMP_STRUCT odbcTime;
      
      ret = SQLGetData(
        hStmt, 
        column.index, 
        SQL_C_TYPE_TIMESTAMP,
        &odbcTime, 
        bufferLength, 
        &len);

      DEBUG_PRINTF("ODBC::GetColumnValue - Unix Timestamp: index=%i name=%s type=%i len=%i\n", 
                    column.index, column.name, column.type, len);

      if(len == SQL_NULL_DATA) {
        return scope.Close(Null());
        //return Null();
      }
      else {
        timeInfo.tm_year = odbcTime.year - 1900;
        timeInfo.tm_mon = odbcTime.month - 1;
        timeInfo.tm_mday = odbcTime.day;
        timeInfo.tm_hour = odbcTime.hour;
        timeInfo.tm_min = odbcTime.minute;
        timeInfo.tm_sec = odbcTime.second;

        //a negative value means that mktime() should use timezone information 
        //and system databases to attempt to determine whether DST is in effect 
        //at the specified time.
        timeInfo.tm_isdst = -1;
          
        return scope.Close(Date::New((double(timegm(&timeInfo)) * 1000) 
                          + (odbcTime.fraction / 1000000)));
        //return Date::New((double(timegm(&timeInfo)) * 1000) 
        //                  + (odbcTime.fraction / 1000000));
      }
#endif
    } break;
    case SQL_BIT :
      //again, i'm not sure if this is cross database safe, but it works for 
      //MSSQL
      ret = SQLGetData(
        hStmt, 
        column.index, 
        SQL_C_CHAR,
        (char *) buffer, 
        bufferLength, 
        &len);

      DEBUG_PRINTF("ODBC::GetColumnValue - Bit: index=%i name=%s type=%i len=%i\n", 
                    column.index, column.name, column.type, len);

      if(len == SQL_NULL_DATA) {
        return scope.Close(Null());
        //return Null();
      }
      else {
        return scope.Close(Boolean::New(( *buffer == '0') ? false : true ));
        //return Boolean::New(( *buffer == '0') ? false : true );
      }
    default :
      Local<String> str;
      int count = 0;
      
      do {
        ret = SQLGetData(
          hStmt,
          column.index,
          SQL_C_TCHAR,
          (char *) buffer,
          bufferLength,
          &len);

        DEBUG_PRINTF("ODBC::GetColumnValue - String: index=%i name=%s type=%i len=%i value=%s ret=%i bufferLength=%i\n", 
                      column.index, column.name, column.type, len,(char *) buffer, ret, bufferLength);

        if(len == SQL_NULL_DATA) {
          return scope.Close(Null());
          //return Null();
        }
        
        if (SQL_NO_DATA == ret) {
          //we have captured all of the data
          break;
        }
        else if (SQL_SUCCEEDED(ret)) {
          //we have not captured all of the data yet
          
          if (count == 0) {
            //no concatenation required, this is our first pass
#ifdef UNICODE
            str = String::New((uint16_t*) buffer);
#else
            str = String::New((char *) buffer);
#endif
          }
          else {
            //we need to concatenate
#ifdef UNICODE
            str = String::Concat(str, String::New((uint16_t*) buffer));
#else
            str = String::Concat(str, String::New((char *) buffer));
#endif
          }
          
          count += 1;
        }
        else {
          //an error has occured
          char *errorMessage = "ODBC::GetColumnValue - String: - ERROR";
          DEBUG_PRINTF("%s\n", errorMessage);
          
          Local<Object> objError = Object::New();
          objError->SetPrototype(Exception::Error(String::New(errorMessage)));
          objError->Set(String::New("message"), String::New(errorMessage));
          objError->Set(String::New("state"), String::New("F****D UP"));
          
          return ThrowException(scope.Close(objError));
          // ThrowException(ODBC::GetSQLError(
          //   SQL_HANDLE_STMT,
          //   hStmt,
          //   (char *) "[node-odbc] Error in ODBC::GetColumnValue"
          // ));
          
          break;
        }
      } while (true);
      
      return scope.Close(str);
      //return str;
  }
}
Пример #9
0
void MetadataNode::InterfaceConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
	try
	{
		SET_PROFILER_FRAME();

		auto isolate = info.GetIsolate();
		auto thiz = info.This();
		auto node = reinterpret_cast<MetadataNode*>(info.Data().As<External>()->Value());

		Local<Object> implementationObject;
		Local<String> v8ExtendName;
		string extendLocation;
		bool extendLocationFound = GetExtendLocation(extendLocation);
		if (info.Length() == 1)
		{
			if (!extendLocationFound)
			{
		stringstream ss;
				ss << "(InternalError): Invalid extend() call. No name specified for extend. Location: " << extendLocation.c_str();
				throw NativeScriptException(ss.str());
			}

			if (!info[0]->IsObject())
			{
				throw NativeScriptException(string("First argument must be implementation object"));
			}
			implementationObject = info[0]->ToObject();
		}
		else if (info.Length() == 2)
		{
			if (!info[0]->IsString())
			{
				throw NativeScriptException(string("First argument must be string"));
			}
			if (!info[1]->IsObject())
			{
				throw NativeScriptException(string("Second argument must be implementation object"));
			}

			DEBUG_WRITE("InterfaceConstructorCallback: getting extend name");
			v8ExtendName = info[0]->ToString();
			implementationObject = info[1]->ToObject();
		}
		else
		{
			throw NativeScriptException(string("Invalid number of arguments"));
		}

		auto className = node->m_implType;
		auto extendName = ConvertToString(v8ExtendName);
		auto extendNameAndLocation = extendLocation + extendName;
		SetInstanceMetadata(isolate, implementationObject, node);

		//@@@ Refactor
		thiz->SetInternalField(static_cast<int>(ObjectManager::MetadataNodeKeys::CallSuper), True(isolate));

		string fullClassName = CreateFullClassName(className, extendNameAndLocation);

		implementationObject->SetPrototype(thiz->GetPrototype());
		thiz->SetPrototype(implementationObject);
		thiz->SetHiddenValue(ConvertToV8String("t::implObj"), implementationObject);

		ArgsWrapper argWrapper(info, ArgType::Interface, Local<Object>());

		auto success = NativeScriptRuntime::RegisterInstance(thiz, fullClassName, argWrapper, implementationObject, true);
	}
	catch (NativeScriptException& e)
	{
		e.ReThrowToV8();
	}
	catch (std::exception e) {
		stringstream ss;
		ss << "Error: c++ exception: " << e.what() << endl;
		NativeScriptException nsEx(ss.str());
		nsEx.ReThrowToV8();
	}
	catch (...) {
		NativeScriptException nsEx(std::string("Error: c++ exception!"));
		nsEx.ReThrowToV8();
	}
}
Пример #10
0
Local<Object> ODBC::GetSQLError (SQLSMALLINT handleType, SQLHANDLE handle, char* message) {
    Nan::EscapableHandleScope scope;

    DEBUG_PRINTF("ODBC::GetSQLError : handleType=%i, handle=%p\n", handleType, handle);

    Local<Object> objError = Nan::New<Object>();

    SQLINTEGER i = 0;
    SQLINTEGER native;

    SQLSMALLINT len;
    SQLINTEGER statusRecCount;
    SQLRETURN ret;
    char errorSQLState[14];
    char errorMessage[ERROR_MESSAGE_BUFFER_BYTES];

    ret = SQLGetDiagField(
              handleType,
              handle,
              0,
              SQL_DIAG_NUMBER,
              &statusRecCount,
              SQL_IS_INTEGER,
              &len);

    // Windows seems to define SQLINTEGER as long int, unixodbc as just int... %i should cover both
    DEBUG_PRINTF("ODBC::GetSQLError : called SQLGetDiagField; ret=%i, statusRecCount=%i\n", ret, statusRecCount);

    Local<Array> errors = Nan::New<Array>();
    objError->Set(Nan::New("errors").ToLocalChecked(), errors);

    for (i = 0; i < statusRecCount; i++) {
        DEBUG_PRINTF("ODBC::GetSQLError : calling SQLGetDiagRec; i=%i, statusRecCount=%i\n", i, statusRecCount);

        ret = SQLGetDiagRec(
                  handleType,
                  handle,
                  (SQLSMALLINT)(i + 1),
                  (SQLTCHAR *) errorSQLState,
                  &native,
                  (SQLTCHAR *) errorMessage,
                  ERROR_MESSAGE_BUFFER_CHARS,
                  &len);

        DEBUG_PRINTF("ODBC::GetSQLError : after SQLGetDiagRec; i=%i\n", i);

        if (SQL_SUCCEEDED(ret)) {
            DEBUG_PRINTF("ODBC::GetSQLError : errorMessage=%s, errorSQLState=%s\n", errorMessage, errorSQLState);

            if (i == 0) {
                // First error is assumed the primary error
                objError->Set(Nan::New("error").ToLocalChecked(), Nan::New(message).ToLocalChecked());
#ifdef UNICODE
                objError->SetPrototype(Exception::Error(Nan::New((uint16_t *)errorMessage).ToLocalChecked()));
                objError->Set(Nan::New("message").ToLocalChecked(), Nan::New((uint16_t *)errorMessage).ToLocalChecked());
                objError->Set(Nan::New("state").ToLocalChecked(), Nan::New((uint16_t *)errorSQLState).ToLocalChecked());
#else
                objError->SetPrototype(Exception::Error(Nan::New(errorMessage).ToLocalChecked()));
                objError->Set(Nan::New("message").ToLocalChecked(), Nan::New(errorMessage).ToLocalChecked());
                objError->Set(Nan::New("state").ToLocalChecked(), Nan::New(errorSQLState).ToLocalChecked());
#endif
            }

            Local<Object> subError = Nan::New<Object>();

#ifdef UNICODE
            subError->Set(Nan::New("message").ToLocalChecked(), Nan::New((uint16_t *)errorMessage).ToLocalChecked());
            subError->Set(Nan::New("state").ToLocalChecked(), Nan::New((uint16_t *)errorSQLState).ToLocalChecked());
#else
            subError->Set(Nan::New("message").ToLocalChecked(), Nan::New(errorMessage).ToLocalChecked());
            subError->Set(Nan::New("state").ToLocalChecked(), Nan::New(errorSQLState).ToLocalChecked());
#endif
            errors->Set(Nan::New(i), subError);

        } else if (ret == SQL_NO_DATA) {
            break;
        }
    }

    if (statusRecCount == 0) {
        //Create a default error object if there were no diag records
        objError->Set(Nan::New("error").ToLocalChecked(), Nan::New(message).ToLocalChecked());
        objError->SetPrototype(Exception::Error(Nan::New(message).ToLocalChecked()));
        objError->Set(Nan::New("message").ToLocalChecked(), Nan::New(
                          (const char *) "[node-odbc] An error occurred but no diagnostic information was available.").ToLocalChecked());
    }

    return scope.Escape(objError);
}
Пример #11
0
Local<Object> ODBC::GetSQLError (SQLSMALLINT handleType, SQLHANDLE handle, char* message) {
  HandleScope scope;
  
  DEBUG_PRINTF("ODBC::GetSQLError : handleType=%i, handle=%p\n", handleType, handle);
  
  Local<Object> objError = Object::New();
  Local<String> str = String::New("");

  SQLINTEGER i = 0;
  SQLINTEGER native;
  
  SQLSMALLINT len;
  SQLINTEGER statusRecCount;
  SQLRETURN ret;
  char errorSQLState[14];
  char errorMessage[ERROR_MESSAGE_BUFFER_BYTES];

  ret = SQLGetDiagField(
    handleType,
    handle,
    0,
    SQL_DIAG_NUMBER,
    &statusRecCount,
    SQL_IS_INTEGER,
    &len);

  // Windows seems to define SQLINTEGER as long int, unixodbc as just int... %i should cover both
  DEBUG_PRINTF("ODBC::GetSQLError : called SQLGetDiagField; ret=%i, statusRecCount=%i\n", ret, statusRecCount);

  for (i = 0; i < statusRecCount; i++){
    DEBUG_PRINTF("ODBC::GetSQLError : calling SQLGetDiagRec; i=%i, statusRecCount=%i\n", i, statusRecCount);
    
    ret = SQLGetDiagRec(
      handleType, 
      handle,
      i + 1, 
      (SQLTCHAR *) errorSQLState,
      &native,
      (SQLTCHAR *) errorMessage,
      ERROR_MESSAGE_BUFFER_CHARS,
      &len);
    
    DEBUG_PRINTF("ODBC::GetSQLError : after SQLGetDiagRec; i=%i\n", i);

    if (SQL_SUCCEEDED(ret)) {
      DEBUG_PRINTF("ODBC::GetSQLError : errorMessage=%s, errorSQLState=%s\n", errorMessage, errorSQLState);

      objError->Set(String::New("error"), String::New(message));
#ifdef UNICODE
      str = String::Concat(str, String::New((uint16_t *) errorMessage));

      objError->SetPrototype(Exception::Error(String::New((uint16_t *) errorMessage)));
      objError->Set(String::New("message"), str);
      objError->Set(String::New("state"), String::New((uint16_t *) errorSQLState));
#else
      str = String::Concat(str, String::New(errorMessage));

      objError->SetPrototype(Exception::Error(String::New(errorMessage)));
      objError->Set(String::New("message"), str);
      objError->Set(String::New("state"), String::New(errorSQLState));
#endif
    } else if (ret == SQL_NO_DATA) {
      break;
    }
  }

  if (statusRecCount == 0) {
    //Create a default error object if there were no diag records
    objError->Set(String::New("error"), String::New(message));
    objError->SetPrototype(Exception::Error(String::New(message)));
    objError->Set(String::New("message"), String::New(
      (const char *) "[node-odbc] An error occurred but no diagnostic information was available."));
  }

  return scope.Close(objError);
}
Пример #12
0
Local<Object> ODBC::GetSQLError (SQLSMALLINT handleType, SQLHANDLE handle, char* message) {
  HandleScope scope;
  
  DEBUG_PRINTF("ODBC::GetSQLError : handleType=%i, handle=%p\n", handleType, handle);
  
  Local<Object> objError = Object::New();
  
  SQLINTEGER i = 0;
  SQLINTEGER native;
  
  SQLSMALLINT len;
  SQLINTEGER numfields;
  SQLRETURN ret;
  char errorSQLState[14];
  char errorMessage[ERROR_MESSAGE_BUFFER_BYTES];

  ret = SQLGetDiagField(
    handleType,
    handle,
    0,
    SQL_DIAG_NUMBER,
    &numfields,
    SQL_IS_INTEGER,
    &len);

  // Windows seems to define SQLINTEGER as long int, unixodbc as just int... %i should cover both
  DEBUG_PRINTF("ODBC::GetSQLError : called SQLGetDiagField; ret=%i\n", ret);
  
  for (i = 0; i < numfields; i++){
    DEBUG_PRINTF("ODBC::GetSQLError : calling SQLGetDiagRec; i=%i, numfields=%i\n", i, numfields);
    
    ret = SQLGetDiagRec(
      handleType, 
      handle,
      i + 1, 
      (SQLTCHAR *) errorSQLState,
      &native,
      (SQLTCHAR *) errorMessage,
      ERROR_MESSAGE_BUFFER_CHARS,
      &len);
    
    DEBUG_PRINTF("ODBC::GetSQLError : after SQLGetDiagRec; i=%i\n", i);

    if (SQL_SUCCEEDED(ret)) {
      DEBUG_TPRINTF(SQL_T("ODBC::GetSQLError : errorMessage=%s, errorSQLState=%s\n"), errorMessage, errorSQLState);
      
      objError->Set(String::New("error"), String::New(message));
#ifdef UNICODE
      objError->SetPrototype(Exception::Error(String::New((uint16_t *) errorMessage)));
      objError->Set(String::New("message"), String::New((uint16_t *) errorMessage));
      objError->Set(String::New("state"), String::New((uint16_t *) errorSQLState));
#else
      objError->SetPrototype(Exception::Error(String::New(errorMessage)));
      objError->Set(String::New("message"), String::New(errorMessage));
      objError->Set(String::New("state"), String::New(errorSQLState));
#endif
    } else if (ret == SQL_NO_DATA) {
      break;
    }
  }
  
  return scope.Close(objError);
}