예제 #1
0
파일: core.c 프로젝트: NaldoDj/core
static HB_ERRCODE odbcGoTo( SQLBASEAREAP pArea, HB_ULONG ulRecNo )
{
   SQLHSTMT  hStmt;
   SQLRETURN res;
   SQLLEN    iLen;
   PHB_ITEM  pArray, pItem;
   LPFIELD   pField;
   HB_USHORT ui;

   /* No pArea->pSDDData for DBCreate() area...
    * though pArea->fFetched == HB_TRUE for them
    */
   hStmt = pArea->pSDDData ? ( ( SDDDATA * ) pArea->pSDDData )->hStmt : NULL;

   while( ulRecNo > pArea->ulRecCount && ! pArea->fFetched )
   {
      if( ! SQL_SUCCEEDED( SQLFetch( hStmt ) ) )
      {
         pArea->fFetched = HB_TRUE;
         break;
      }

      pArray = hb_itemArrayNew( pArea->area.uiFieldCount );
      pItem  = NULL;
      for( ui = 1; ui <= pArea->area.uiFieldCount; ui++ )
      {
         iLen   = SQL_NULL_DATA;
         res    = 0;
         pField = pArea->area.lpFields + ui - 1;
         switch( pField->uiType )
         {
            case HB_FT_STRING:
               if( pField->uiType & HB_FF_BINARY )
               {
                  char buffer[ 1 ];

                  iLen = 0;
                  if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_BINARY, buffer, 0, &iLen ) ) )
                  {
                     if( iLen >= 0 )
                     {
                        char * val = ( char * ) hb_xgrab( iLen + 1 );
                        if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_BINARY, val, iLen + 1, &iLen ) ) )
                           pItem = hb_itemPutCLPtr( pItem, val, ( HB_SIZE ) iLen );
                        else
                           hb_xfree( val );
                     }
                  }
               }
               else
               {
                  O_HB_CHAR buffer[ 1 ];
#if defined( UNICODE )
                  SQLSMALLINT iTargetType = SQL_C_WCHAR;
#else
                  SQLSMALLINT iTargetType = SQL_C_CHAR;
#endif

                  iLen = 0;
                  if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, iTargetType, buffer, 0, &iLen ) ) )
                  {
                     if( iLen >= 0 )
                     {
                        O_HB_CHAR * val = ( O_HB_CHAR * ) hb_xgrab( iLen + sizeof( O_HB_CHAR ) );
                        if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, iTargetType, val, iLen + sizeof( O_HB_CHAR ), &iLen ) ) )
                        {
#if defined( UNICODE )
                           iLen >>= 1;
#endif
                           pItem = O_HB_ITEMPUTSTRLEN( pItem, val, ( HB_SIZE ) iLen );
                        }
                        hb_xfree( val );
                     }
                  }
               }
               break;

            case HB_FT_INTEGER:
#if ODBCVER >= 0x0300
               if( pField->uiTypeExtended == ( HB_USHORT ) SQL_BIGINT )
               {
                  HB_I64 val = 0;
                  /* NOTE: SQL_C_SBIGINT not available before ODBC 3.0 */
                  if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_SBIGINT, &val, sizeof( val ), &iLen ) ) )
                     pItem = hb_itemPutNIntLen( pItem, val, pField->uiLen );
               }
               else
#endif
               {
                  SQLINTEGER val = 0;
                  if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_LONG, &val, sizeof( val ), &iLen ) ) )
                     pItem = hb_itemPutNLLen( pItem, val, pField->uiLen );
               }
               break;

            case HB_FT_LONG:
               if( pField->uiDec == 0 && pField->uiLen < 10 )
               {
                  SQLINTEGER val = 0;
                  if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_LONG, &val, sizeof( val ), &iLen ) ) )
                     pItem = hb_itemPutNLLen( pItem, val, pField->uiLen );
               }
               else
               {
                  double val = 0.0;
                  if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_DOUBLE, &val, sizeof( val ), &iLen ) ) )
                     pItem = hb_itemPutNDLen( pItem, val, pField->uiLen, pField->uiDec );
               }
               break;

            case HB_FT_DOUBLE:
            {
               double val = 0.0;
               if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_DOUBLE, &val, sizeof( val ), &iLen ) ) )
                  pItem = hb_itemPutNDLen( pItem, val, pField->uiLen, pField->uiDec );
               break;
            }

            case HB_FT_LOGICAL:
            {
               unsigned char val = 0;
               if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_BIT, &val, sizeof( val ), &iLen ) ) )
                  pItem = hb_itemPutL( pItem, val != 0 );
               break;
            }

            case HB_FT_DATE:
            {
               DATE_STRUCT val = { 0, 0, 0 };
               if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_DATE, &val, sizeof( val ), &iLen ) ) )
                  pItem = hb_itemPutD( pItem, val.year, val.month, val.day );
               break;
            }

            case HB_FT_TIME:
            {
               TIME_STRUCT val = { 0, 0, 0 };
               if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_TIME, &val, sizeof( val ), &iLen ) ) )
                  pItem = hb_itemPutTDT( pItem, 0, hb_timeEncode( val.hour, val.minute, val.second, 0 ) );
               break;
            }

            case HB_FT_TIMESTAMP:
            {
               TIMESTAMP_STRUCT val = { 0, 0, 0, 0, 0, 0, 0 };
               if( SQL_SUCCEEDED( res = SQLGetData( hStmt, ui, SQL_C_TIMESTAMP, &val, sizeof( val ), &iLen ) ) )
                  pItem = hb_itemPutTDT( pItem, hb_dateEncode( val.year, val.month, val.day ),
                                         hb_timeEncode( val.hour, val.minute, val.second, val.fraction / 1000000 ) );
               break;
            }
         }

         /* TODO: check SQL_SUCCEEDED( res ) */
         /* TODO: check for SQL_NO_TOTAL. What does this mean? */
         HB_SYMBOL_UNUSED( res );

         if( pItem )
         {
            /* NULL -> NIL */
            if( iLen == SQL_NULL_DATA )
               hb_itemClear( pItem );
            else
               hb_arraySetForward( pArray, ui, pItem );
         }
      }
      if( pItem )
         hb_itemRelease( pItem );

      if( pArea->ulRecCount + 1 >= pArea->ulRecMax )
      {
         pArea->pRow      = ( void ** ) hb_xrealloc( pArea->pRow, ( pArea->ulRecMax + SQLDD_ROWSET_RESIZE ) * sizeof( void * ) );
         pArea->pRowFlags = ( HB_BYTE * ) hb_xrealloc( pArea->pRowFlags, ( pArea->ulRecMax + SQLDD_ROWSET_RESIZE ) * sizeof( HB_BYTE ) );
         pArea->ulRecMax += SQLDD_ROWSET_RESIZE;
      }

      pArea->ulRecCount++;
      pArea->pRow[ pArea->ulRecCount ]      = pArray;
      pArea->pRowFlags[ pArea->ulRecCount ] = SQLDD_FLAG_CACHED;
   }
예제 #2
0
파일: core.c 프로젝트: raulpjr/harbour-core
static HB_ERRCODE odbcOpen( SQLBASEAREAP pArea )
{
   SDDCONN *   pSDDConn = ( SDDCONN * ) pArea->pConnection->pSDDConn;
   SDDDATA *   pSDDData;
   void *      hQuery;
   SQLHSTMT    hStmt;
   SQLSMALLINT iNameLen;
   PHB_ITEM    pItemEof, pItem;
   HB_BOOL     bError;
   HB_USHORT   uiFields, uiIndex;
   HB_ERRCODE  errCode;
   char *      szError;

   pArea->pSDDData = memset( hb_xgrab( sizeof( SDDDATA ) ), 0, sizeof( SDDDATA ) );
   pSDDData        = ( SDDDATA * ) pArea->pSDDData;

#if ODBCVER >= 0x0300
   if( ! SQL_SUCCEEDED( SQLAllocHandle( SQL_HANDLE_STMT, pSDDConn->hConn, &hStmt ) ) )
#else
   if( ! SQL_SUCCEEDED( SQLAllocStmt( pSDDConn->hConn, &hStmt ) ) )
#endif
   {
      szError = odbcGetError( pSDDConn->hEnv, pSDDConn->hConn, SQL_NULL_HSTMT, &errCode );
      hb_errRT_ODBCDD( EG_OPEN, ESQLDD_STMTALLOC, szError, pArea->szQuery, errCode );
      hb_xfree( szError );
      return HB_FAILURE;
   }

   pItem = hb_itemPutC( NULL, pArea->szQuery );

   if( ! SQL_SUCCEEDED( SQLExecDirect( hStmt,
                                       ( SQLTCHAR * ) O_HB_ITEMGETSTR( pItem, &hQuery, NULL ),
                                       ( SQLINTEGER ) hb_itemGetCLen( pItem ) ) ) )
   {
      hb_strfree( hQuery );
      hb_itemRelease( pItem );
      szError = odbcGetError( pSDDConn->hEnv, pSDDConn->hConn, hStmt, &errCode );
#if ODBCVER >= 0x0300
      SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
#else
      SQLFreeStmt( hStmt, SQL_DROP );
#endif
      hb_errRT_ODBCDD( EG_OPEN, ESQLDD_INVALIDQUERY, szError, pArea->szQuery, errCode );
      hb_xfree( szError );
      return HB_FAILURE;
   }
   else
   {
      hb_strfree( hQuery );
      hb_itemRelease( pItem );
   }

   if( ! SQL_SUCCEEDED( SQLNumResultCols( hStmt, &iNameLen ) ) )
   {
      szError = odbcGetError( pSDDConn->hEnv, pSDDConn->hConn, hStmt, &errCode );
#if ODBCVER >= 0x0300
      SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
#else
      SQLFreeStmt( hStmt, SQL_DROP );
#endif
      hb_errRT_ODBCDD( EG_OPEN, ESQLDD_STMTDESCR + 1000, szError, pArea->szQuery, errCode );
      hb_xfree( szError );
      return HB_FAILURE;
   }

   uiFields = ( HB_USHORT ) iNameLen;
   SELF_SETFIELDEXTENT( ( AREAP ) pArea, uiFields );

   pItemEof = hb_itemArrayNew( uiFields );

#if 0
   HB_TRACE( HB_TR_ALWAYS, ( "fieldcount=%d", iNameLen ) );
#endif

   errCode = 0;
   bError  = HB_FALSE;
   for( uiIndex = 0; uiIndex < uiFields; uiIndex++ )
   {
      DBFIELDINFO pFieldInfo;

      PHB_ITEM pName;

      SQLTCHAR    cName[ 256 ];
      SQLULEN     uiSize;
      SQLSMALLINT iDataType, iDec, iNull;

      if( ! SQL_SUCCEEDED( SQLDescribeCol( hStmt, ( SQLSMALLINT ) uiIndex + 1, ( SQLTCHAR * ) cName, HB_SIZEOFARRAY( cName ), &iNameLen, &iDataType, &uiSize, &iDec, &iNull ) ) )
      {
         hb_itemRelease( pItemEof );
         szError = odbcGetError( pSDDConn->hEnv, pSDDConn->hConn, hStmt, NULL );
#if ODBCVER >= 0x0300
         SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
#else
         SQLFreeStmt( hStmt, SQL_DROP );
#endif
         hb_errRT_ODBCDD( EG_OPEN, ESQLDD_STMTDESCR + 1001, szError, pArea->szQuery, 0 );
         hb_xfree( szError );
         return HB_FAILURE;
      }

      pName = O_HB_ITEMPUTSTRLEN( NULL, ( O_HB_CHAR * ) cName, iNameLen );
      pFieldInfo.atomName = hb_itemGetCPtr( pName );

      /*
         We do mapping of many SQL types to one Harbour field type here, so, we need store
         real SQL type in uiTypeExtended. SQL types are signed, so, HB_USHORT type casting
         is a little hacky. We need to remember use this casting also in expressions like
         this:
            if( pField->uiTypeExtended == ( HB_USHORT ) SQL_BIGINT )
         or introduce our own unsigned SQL types.
         [Mindaugas]
       */
      pFieldInfo.uiTypeExtended = ( HB_USHORT ) iDataType;
      pFieldInfo.uiLen = ( HB_USHORT ) uiSize;
      pFieldInfo.uiDec = iDec;

#if 0
      HB_TRACE( HB_TR_ALWAYS, ( "field: name=%s type=%d len=%d dec=%d null=%d", pFieldInfo.atomName, iDataType, uiSize, iDec, iNull ) );
#endif

      switch( iDataType )
      {
         case SQL_CHAR:
         case SQL_VARCHAR:
         case SQL_LONGVARCHAR:
         case SQL_WCHAR:
         case SQL_WVARCHAR:
         case SQL_WLONGVARCHAR:
            pFieldInfo.uiType = HB_FT_STRING;
            break;

         case SQL_VARBINARY:
         case SQL_LONGVARBINARY:
            pFieldInfo.uiType  = HB_FT_STRING;
            pFieldInfo.uiFlags = HB_FF_BINARY;
            break;

         case SQL_TINYINT:
         case SQL_SMALLINT:
         case SQL_INTEGER:
         case SQL_BIGINT:
            pFieldInfo.uiType = HB_FT_INTEGER;
            break;

         case SQL_DECIMAL:
         case SQL_NUMERIC:
            pFieldInfo.uiType = HB_FT_LONG;
            break;

         case SQL_REAL:
         case SQL_FLOAT:
         case SQL_DOUBLE:
            pFieldInfo.uiType = HB_FT_DOUBLE;
            break;

         case SQL_BIT:
            pFieldInfo.uiType = HB_FT_LOGICAL;
            break;

         case SQL_DATE:
#if ODBCVER >= 0x0300
         case SQL_TYPE_DATE:
#endif
            pFieldInfo.uiType = HB_FT_DATE;
            break;

         case SQL_TIME:
#if ODBCVER >= 0x0300
         case SQL_TYPE_TIME:
#endif
            pFieldInfo.uiType = HB_FT_DATE;
            break;

         /*  SQL_DATETIME = SQL_DATE = 9 */
         case SQL_TIMESTAMP:
#if ODBCVER >= 0x0300
         case SQL_TYPE_TIMESTAMP:
#endif
            pFieldInfo.uiType = HB_FT_TIMESTAMP;
            break;

         default:
#if 0
            HB_TRACE( HB_TR_ALWAYS, ( "new sql type=%d", iDataType ) );
#endif
            bError  = HB_TRUE;
            errCode = ( HB_ERRCODE ) iDataType;
            pFieldInfo.uiType = 0;
            pFieldInfo.uiType = HB_FT_STRING;
            break;
      }

      if( ! bError )
      {
         switch( pFieldInfo.uiType )
         {
            case HB_FT_STRING:
            {
               char * pStr;

               pStr = ( char * ) hb_xgrab( ( HB_SIZE ) pFieldInfo.uiLen + 1 );
               memset( pStr, ' ', pFieldInfo.uiLen );
               pStr[ pFieldInfo.uiLen ] = '\0';

               pItem = hb_itemPutCL( NULL, pStr, pFieldInfo.uiLen );
               hb_xfree( pStr );
               break;
            }

            case HB_FT_MEMO:
               pItem = hb_itemPutC( NULL, NULL );
               break;

            case HB_FT_INTEGER:
               pItem = hb_itemPutNI( NULL, 0 );
               break;

            case HB_FT_LONG:
               if( pFieldInfo.uiDec == 0 )
                  pItem = hb_itemPutNLLen( NULL, 0, pFieldInfo.uiLen );
               else
                  pItem = hb_itemPutNDLen( NULL, 0.0, pFieldInfo.uiLen, pFieldInfo.uiDec );
               break;

            case HB_FT_DOUBLE:
               pItem = hb_itemPutNDLen( NULL, 0.0, pFieldInfo.uiLen, pFieldInfo.uiDec );
               break;

            case HB_FT_LOGICAL:
               pItem = hb_itemPutL( NULL, HB_FALSE );
               break;

            case HB_FT_DATE:
               pItem = hb_itemPutDL( NULL, 0 );
               break;

            case HB_FT_TIME:
               pItem = hb_itemPutTDT( NULL, 0, 0 );
               break;

            case HB_FT_TIMESTAMP:
               pItem = hb_itemPutTDT( NULL, 0, 0 );
               break;

            default:
               pItem  = hb_itemNew( NULL );
               bError = HB_TRUE;
               break;
         }

         hb_arraySetForward( pItemEof, uiIndex + 1, pItem );
         hb_itemRelease( pItem );

         if( ! bError )
            bError = ( SELF_ADDFIELD( ( AREAP ) pArea, &pFieldInfo ) == HB_FAILURE );
      }

      hb_itemRelease( pName );

      if( bError )
         break;
   }

   if( bError )
   {
      hb_itemRelease( pItemEof );
#if ODBCVER >= 0x0300
      SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
#else
      SQLFreeStmt( hStmt, SQL_DROP );
#endif
      hb_errRT_ODBCDD( EG_CORRUPTION, ESQLDD_INVALIDFIELD, "Invalid field type", pArea->szQuery, errCode );
      return HB_FAILURE;
   }

   pArea->ulRecCount = 0;
   pArea->ulRecMax   = SQLDD_ROWSET_INIT;

   pArea->pRow = ( void ** ) hb_xgrab( SQLDD_ROWSET_INIT * sizeof( void * ) );
   memset( pArea->pRow, 0, SQLDD_ROWSET_INIT * sizeof( void * ) );
   pArea->pRowFlags = ( HB_BYTE * ) hb_xgrab( SQLDD_ROWSET_INIT * sizeof( HB_BYTE ) );
   memset( pArea->pRowFlags, 0, SQLDD_ROWSET_INIT * sizeof( HB_BYTE ) );

   pArea->pRow[ 0 ]      = pItemEof;
   pArea->pRowFlags[ 0 ] = SQLDD_FLAG_CACHED;

   pSDDData->hStmt = hStmt;
   return HB_SUCCESS;
}