예제 #1
0
// This native method is called by the LmT2Driver Java class
// whenever a java.sql.Connection object of type default connection 
// is created. The default connection's object reference is passed 
// as input to this method.
//
// This method creates a global reference of the provided connection
// object and adds it to 'lmUtilityConnList'.
//
JNIEXPORT void JNICALL Java_com_tandem_sqlmx_LmT2Driver_addConnection
(JNIEnv * env, jclass jc, jobject conn)
{
  LM_ASSERT( conn != NULL );
  jobject newConn = env->NewGlobalRef( conn );
  lmUtilityConnList.insert(newConn);
}
LmRoutineCppObj::~LmRoutineCppObj()
{
  // assert that caller has called dealloc before destroying this object
  LM_ASSERT(invocationInfo_ == NULL &&
            interfaceObj_ == NULL &&
            outputRow_ == NULL);
}
예제 #3
0
// Deletes the LmResultSet object at a given index.
void LmRoutineJava::cleanupLmResultSet(ComUInt32 index,
                                       ComDiagsArea *diagsArea)
{
  LM_ASSERT(index < resultSetList_.entries());

  ((LmResultSetJava *)resultSetList_[index])->close( diagsArea );
  resultSetList_.removeAt(index);
}
예제 #4
0
// This method creates a LmResultSetJava object for the 
// passed in java.sql.ResultSet object (newRS) and inserts 
// it into resultSetList_.
//
// Parameters:
// newRS    - A java.sql.ResultSet object
// paramPos - The position (1-based) of newRS
//            in the Java method signature.
// da       - ComDiagsArea object to report any errors. 
//            This object should not be NULL.
LmResult LmRoutineJava::populateResultSetInfo(LmHandle newRS, Int32 paramPos, 
                                              ComDiagsArea *da)
{
  LmResult result = LM_OK;
  jobject newRSRef = (jobject)newRS;

  LM_ASSERT(da != NULL);

  // SPJ method can return same java.sql.ResultSet object in 
  // multiple OUT params but we ignore such duplicates.
  // We also ignore a NULL java.sql.ResultSet object.
  if( newRSRef == NULL || isDuplicateRS( newRSRef ))
    return result;

  LmResultSetJava::LmResultSetInfoStatus rsInfoStatus;

  LmResultSetJava *newLmRS = 
			  new (collHeap()) LmResultSetJava( getLM(),
                                          (LmHandle)newRSRef,
                                          paramPos,
                                          getNameForDiags(),
                                          rsInfoStatus,
                                          connectionList_,
                                          da );

  // If the constructor returned a success status then insert 
  // the newLmRS object into resultSetList_ otherwise delete it.
  if( rsInfoStatus == LmResultSetJava::RS_INFO_OK ) {

    // Order the objects inserted in the resultSetList_ based on
    // the order in which the result set cursors were opened.
    ComUInt32 i;
    LmResultSetJava *lmRS;
    for( i = 0; i < resultSetList_.entries(); i++ )
    {
      lmRS = (LmResultSetJava *)resultSetList_[i];
      if( newLmRS->rsCounter_ < lmRS->rsCounter_ )
        break;
    }
    resultSetList_.insertAt( i, newLmRS );
  }
  else {
    delete newLmRS;
    newLmRS = NULL;

    // Ignore closed result sets
    if( rsInfoStatus == LmResultSetJava::RS_INFO_CLOSED )
      result = LM_OK;
    else
      result = LM_ERR;
  }

  return result;
}
예제 #5
0
LmResult LmLanguageManagerC::invokeRoutine(
  LmRoutine    *handle,
  void         *inputRow,
  void         *outputRow,
  ComDiagsArea *diagsArea)
{
  LmRoutine *routine = (LmRoutine *) handle;
  LM_ASSERT(routine);
  LmResult result = routine->invokeRoutine(inputRow, outputRow, diagsArea);


  return result;
}
예제 #6
0
// Deletes the given LmResultSet object.
// Any error during the close will be reported in the
// diagsArea, if available. Asserts on an invalid pointer.
void LmRoutineJava::cleanupLmResultSet(LmResultSet *resultSet,
                                       ComDiagsArea *diagsArea)
{
  for (ComUInt32 index=0; index < resultSetList_.entries(); index++)
  {
    if (resultSetList_[index] == resultSet)
    {
      ((LmResultSetJava *)resultSetList_[index])->close(diagsArea);
      resultSetList_.removeAt(index);

      return;
    }
  }

  // passed in resultset param is not a valid LmResultSet pointer.
  LM_ASSERT(0);
}
예제 #7
0
// This method checks if the passed in java.sql.ResultSet object
// reference (newRS) is already part of a LmResultSetJava
// object in the resultSetList_.
//
// The parameter newRS should not be NULL.
// Returns TRUE if a match is found FALSE otherwise
NABoolean LmRoutineJava::isDuplicateRS( LmHandle newRS )
{
  JNIEnv *jni = (JNIEnv*)getLM()->jniEnv_;
  LmResultSetJava *lmRS;
  jobject newRSRef = (jobject)newRS;
  ComUInt32 indx;

  LM_ASSERT(newRS != NULL);

  for (indx = 0; indx < resultSetList_.entries(); indx++)
  {
	  lmRS = (LmResultSetJava *)resultSetList_[indx];

    // IsSameObject() JNI call compares the object references
    // of it's parameters
	  if (jni->IsSameObject( (jobject)lmRS->getResultSet(), newRSRef ))
	    return TRUE;

  }  // End for loop

  return FALSE;
}
LmRoutineCSql::LmRoutineCSql(const char   *sqlName,
                             const char   *externalName,
                             const char   *librarySqlName,
                             ComUInt32    numSqlParam,
                             char         *routineSig,
                             ComUInt32    maxResultSets,
                             ComRoutineTransactionAttributes transactionAttrs,
                             ComRoutineSQLAccess sqlAccessMode,
                             ComRoutineExternalSecurity externalSecurity,
                             Int32 routineOwnerId,
                             const char   *parentQid,
                             ComUInt32    inputRowLen,
                             ComUInt32    outputRowLen,
                             const char   *currentUserName,
                             const char   *sessionUserName,
                             LmParameter  *parameters,
                             LmLanguageManagerC *lm,
                             LmHandle     routine,
                             LmContainer  *container,
                             ComDiagsArea *diagsArea)
  : LmRoutineC(sqlName, externalName, librarySqlName, numSqlParam, routineSig,
               maxResultSets,
               COM_LANGUAGE_C,
               COM_STYLE_SQL,
               transactionAttrs,
               sqlAccessMode,
               externalSecurity, 
	       routineOwnerId,
               parentQid, inputRowLen, outputRowLen,
               currentUserName, sessionUserName, 
               parameters, lm, routine, container, diagsArea),
    cBuf_(NULL),
    data_(NULL),
    ind_(numSqlParam * sizeof(short))
{
  ComUInt32 i = 0;
  data_ = (char **) collHeap()->allocateMemory(numSqlParam * sizeof(char *));
  
  // Allocate C data buffers. Each LmCBuffer instance points to a C
  // buffer and the data_ buffer is an array of pointers to the C data
  // buffers. The LmCBuffer is mainly used to track the actual size of
  // the C buffers because each buffer has some extra bytes at the end
  // to protect against buffer overwrites.
  //
  // cBuf_ -> LmCBuffer  LmCBuffer  LmCBuffer ...
  //            |          |          |
  //            v          v          v
  //           buffer     buffer     buffer   ...
  //             ^          ^          ^
  //             |          |          |
  //          data_[0]   data_[1]   data_[2]  ...
  //

  // NOTE: the cBuf_ array is allocated on the C++ heap because we
  // want to manage the collection as a single array, and we want
  // constructors and destructors to be called when the collection is
  // created and destroyed. Right now, NAMemory and NABasic object
  // interfaces do not provide the appropriate array versions of new
  // and delete operators to accomplish these things.
  cBuf_ = new LmCBuffer[numSqlParam_];
  LM_ASSERT(cBuf_);

  for (i = 0; i < numSqlParam_; i++)
  {
    LmParameter &p = lmParams_[i];
    LmCBuffer &cBuf = cBuf_[i];
    ComUInt32 dataBytes = 0;

    switch (p.direction())
    {
      // NOTE: The code currently supports IN and OUT parameters for C
      // routines. There is no reason we couldn't support INOUT as
      // well, which will be needed if we ever provide stored
      // procedures written in C. But the INOUT code paths have not
      // been implemented yet.
      case COM_INPUT_COLUMN:
        dataBytes = p.inSize();
        break;
      case COM_OUTPUT_COLUMN:
        dataBytes = p.outSize();
        break;
      default:
        LM_ASSERT(0);
        break;
    }

    switch (p.fsType())
    {
      case COM_VCHAR_FSDT:
      case COM_VCHAR_DBL_FSDT:
      {
        // VARCHAR(N) CHARACTER SET ISO88591
        // VARCHAR(N) CHARACTER SET UCS2

        // This is a VARCHAR parameter. Allocate one buffer that will
        // hold the VC struct and the data. Data will begin at the first
        // 8-byte boundary following the VC struct.
        ComUInt32 vcBytes = ROUND8(sizeof(SQLUDR_VC_STRUCT)) + dataBytes;
        cBuf.init(vcBytes);
        data_[i] = cBuf.getBuffer();
        
        // Initialize the VC struct
        SQLUDR_VC_STRUCT *vc = (SQLUDR_VC_STRUCT *) cBuf.getBuffer();
        char *charPtr = (char *) vc;
        vc->data = charPtr + ROUND8(sizeof(SQLUDR_VC_STRUCT));
        vc->length = dataBytes;
      }
      break;

      case COM_FCHAR_FSDT:
      case COM_FCHAR_DBL_FSDT:
      case COM_SIGNED_DECIMAL_FSDT:
      case COM_UNSIGNED_DECIMAL_FSDT:
      case COM_DATETIME_FSDT:
      case COM_SIGNED_NUM_BIG_FSDT:
      case COM_UNSIGNED_NUM_BIG_FSDT:
      {
        // CHAR(N) CHARACTER SET ISO88591
        // CHAR(N) CHARACTER SET UCS2
        // DECIMAL [UNSIGNED]
        // DATE, TIME, TIMESTAMP
        // NUMERIC precision > 18

        // These types require a null-terminated C string. Add one to
        // dataBytes to account for the null terminator.
        cBuf.init(dataBytes + 1);
        data_[i] = cBuf.getBuffer();
      }
      break;

      default:
      {
        // All other types
        cBuf.init(dataBytes);
        data_[i] = cBuf.getBuffer();
      }
      break;

    } // switch (p.fsType())
  } // for each param
    
} // LmRoutineCSql::LmRoutineCSql
예제 #9
0
LmResult LmRoutineJava::invokeRoutine(void *inputRow,
				      void *outputRow,
				      ComDiagsArea *da)
{
  // Delete the LmResultSet objects for re-invocations
  // This will also close the Java result set objects
  // and the Java connections that they are part of
  cleanupResultSets(da);

  // This will close any default connections that do not have 
  // result sets associated with them
  closeDefConnWithNoRS(da);

  // Cleanup the list maintained in LmUtlity.cpp file that will get
  // populated with default connection objects that may get created
  // during this routine's invocation.
  lmUtilityInitConnList((JNIEnv*)getLM()->jniEnv_, (jmethodID)getLM()->connCloseId_);

  // Set the default catalog & schema as system properties. These
  // values are then retrieved by LmSQLMXDriver class for setting
  // it on a getConnection() call
  if (getDefaultCatSchFlag())
  {
    // Determine the catalog & schema values that will be in effect for
    // this UDR. If the values are set globally(with catalog/schema
    // props in CQD) they are used else the catalog/schema of
    // the UDR are used. 
    const char *catalog =
      (getLM()->sysCatalog_) ? getLM()->sysCatalog_ : udrCatalog_;
    const char *schema =
      (getLM()->sysSchema_) ? getLM()->sysSchema_ : udrSchema_;

    if (getLM()->setSystemProperty("sqlmx.udr.catalog", catalog, da) == LM_ERR)
      return LM_ERR;
    if (getLM()->setSystemProperty("sqlmx.udr.schema", schema, da) == LM_ERR)
      return LM_ERR;
  }

  const char *parentQid;
  if ((parentQid = getParentQid()) == NULL)
    parentQid = "NONE";
  if (getLM()->setSystemProperty("sqlmx.udr.parentQid", parentQid, da) == LM_ERR)
      return LM_ERR;
  // Set SQL access mode in LmUtility. This will be checked while SPJ
  // is trying to make a JDBC connection.
  lmUtilitySetSqlAccessMode(getSqlAccessMode());
  
  // Set Transaction Attribute in LmUtility. This will be checked while SPJ
  // is trying to join a transaction.
  lmUtilitySetTransactionAttrs(getTransactionAttrs());

  LmResult result = LM_OK;

  // Set the Definer Authentication Token as system property for
  // Definer Rights SPJs. This value is then retrieved by LmSQLMXDriver class 
  // for setting the password property in getConnection() call.
  if ( externalSecurity_ == COM_ROUTINE_EXTERNAL_SECURITY_DEFINER )
  {
      char *defAuthToken = new (collHeap()) char[DR_SPJ_TOKEN_LEN + 1];
      result = generateDefAuthToken(defAuthToken, da);
      if (result != LM_ERR)
         result = getLM()->setSystemProperty("sqlmx.udr.defAuthToken", defAuthToken, da);
      NADELETEBASIC(defAuthToken, collHeap());
      if (result == LM_ERR)
      {
        char errStr[LMJ_ERR_SIZE_256];
        sprintf (errStr,
                 ": Error returned from setting System Property:  %s.",
       	         "sqlmx.udr.defAuthToken");
        *da << DgSqlCode(-LME_INTERNAL_ERROR)
            << DgString0(errStr);
        return LM_ERR;
      }
  }

  lm_->setRoutineIsActive(TRUE);

  switch (retType_)
  {
    case LmJavaType::JT_VOID:
      result = voidRoutine(outputRow, NULL);
      break;
    default:
      // Other return types are not supported. In the future if we
      // support routines with non-void return types we will need to
      // add case blocks to this switch statement.
      LM_ASSERT(0);
      break;
  }
  
  lm_->setRoutineIsActive(FALSE);

  // Reset the sqlmx.udr.defAuthToken system property for
  // Definer Rights SPJs. 
  if ( externalSecurity_ == COM_ROUTINE_EXTERNAL_SECURITY_DEFINER )
  {
      result = getLM()->clearSystemProperty("sqlmx.udr.defAuthToken", da);
      if (result == LM_ERR)
      {
        char errStr[LMJ_ERR_SIZE_256];
        sprintf (errStr,
                 ": Error returned from Resetting System Property:  %s.",
       	         "sqlmx.udr.defAuthToken");
        *da << DgSqlCode(-LME_INTERNAL_ERROR)
            << DgString0(errStr);
        return LM_ERR;
      }
  }

  // Get the list containing the default connection objects
  // from LmUtility.cpp and create a LmConnection object for 
  // each item in that list.
  NAList<jobject> &connList = lmUtilityGetConnList();
  while(connList.entries())
  {
    jobject conn = connList[0];
    LmConnection *lmConn = 
      new (collHeap()) LmConnection(getLM(), conn,
                                    LmConnection::DEFAULT_CONN, getTransactionAttrs());
    
    connectionList_.insert( lmConn );
    connList.removeAt(0);
  }

  // reset SQL Access mode to COM_UNKNOWN_ROUTINE_SQL_ACCESS
  lmUtilitySetSqlAccessMode(COM_UNKNOWN_ROUTINE_SQL_ACCESS);
  
  // reset Transaction Attributes to COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE
  lmUtilitySetTransactionAttrs(COM_UNKNOWN_ROUTINE_TRANSACTION_ATTRIBUTE);

  return result;
}