From 3f3973cf4001bf0eb33dceccaaa7af37acb230b8 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Sat, 9 Oct 2010 17:07:21 +0000 Subject: [PATCH] 2010-10-09 19:07 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapirdd.h + added new field flag: HB_FF_UNICODE * harbour/contrib/rddads/ads1.c + added support for new ADS 10.0 UNICODE fields: NChar, NVarChar, NMemo They are supported in all ADS* RDDs. --- harbour/ChangeLog | 8 + harbour/contrib/rddads/ads1.c | 288 ++++++++++++++++++++++++---------- harbour/include/hbapirdd.h | 1 + 3 files changed, 214 insertions(+), 83 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 0683bc79df..292092a958 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,14 @@ The license applies to all entries newer than 2009-04-28. */ +2010-10-09 19:07 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapirdd.h + + added new field flag: HB_FF_UNICODE + + * harbour/contrib/rddads/ads1.c + + added support for new ADS 10.0 UNICODE fields: NChar, NVarChar, NMemo + They are supported in all ADS* RDDs. + 2010-10-09 09:58 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/src/lang/msg_tpl.c ! added one missing message diff --git a/harbour/contrib/rddads/ads1.c b/harbour/contrib/rddads/ads1.c index 2633fc97d2..509b480527 100644 --- a/harbour/contrib/rddads/ads1.c +++ b/harbour/contrib/rddads/ads1.c @@ -57,6 +57,7 @@ #include "hbinit.h" #include "hbapi.h" #include "hbapiitm.h" +#include "hbapistr.h" #include "hbapierr.h" #include "hbdbferr.h" #include "hbapilng.h" @@ -1573,10 +1574,38 @@ static HB_ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) break; case 'N': - dbFieldInfo.uiType = HB_FT_LONG; - dbFieldInfo.uiTypeExtended = ADS_NUMERIC; - dbFieldInfo.uiDec = uiDec; - if( uiLen > 32 ) + if( iNameLen == 1 || ! hb_strnicmp( szFieldType, "numeric", 2 ) ) + { + dbFieldInfo.uiType = HB_FT_LONG; + dbFieldInfo.uiTypeExtended = ADS_NUMERIC; + dbFieldInfo.uiDec = uiDec; + if( uiLen > 32 ) + return HB_FAILURE; + } +#if ADS_LIB_VERSION >= 1000 + else if( ! hb_strnicmp( szFieldType, "nchar", 2 ) ) + { + dbFieldInfo.uiType = HB_FT_STRING; + dbFieldInfo.uiFlags = HB_FF_UNICODE; + dbFieldInfo.uiTypeExtended = ADS_NCHAR; + dbFieldInfo.uiLen = uiLen; + } + else if( ! hb_strnicmp( szFieldType, "nvarchar", 2 ) ) + { + dbFieldInfo.uiType = HB_FT_VARLENGTH; + dbFieldInfo.uiFlags = HB_FF_UNICODE; + dbFieldInfo.uiTypeExtended = ADS_NVARCHAR; + dbFieldInfo.uiLen = uiLen; + } + else if( ! hb_strnicmp( szFieldType, "nmemo", 2 ) ) + { + dbFieldInfo.uiType = HB_FT_MEMO; + dbFieldInfo.uiFlags = HB_FF_UNICODE; + dbFieldInfo.uiTypeExtended = ADS_NMEMO; + dbFieldInfo.uiLen = ( pArea->iFileType == ADS_ADT ) ? 9 : ( uiLen == 4 ? 4 : 10 ); + } +#endif + else return HB_FAILURE; break; @@ -1940,6 +1969,8 @@ static HB_ERRCODE adsFieldInfo( AREAP pArea, HB_USHORT uiIndex, HB_USHORT uiType case HB_FT_STRING: if( pField->uiFlags & HB_FF_BINARY ) hb_itemPutC( pItem, "RAW" ); + else if( pField->uiFlags & HB_FF_UNICODE ) + hb_itemPutC( pItem, "NCHAR" ); #ifdef ADS_CISTRING else if( pField->uiTypeExtended == ADS_CISTRING ) hb_itemPutC( pItem, "CICHARACTER" ); @@ -1999,12 +2030,17 @@ static HB_ERRCODE adsFieldInfo( AREAP pArea, HB_USHORT uiIndex, HB_USHORT uiType case HB_FT_VARLENGTH: if( pField->uiFlags & HB_FF_BINARY ) hb_itemPutC( pItem, "VARBINARY" ); + else if( pField->uiFlags & HB_FF_UNICODE ) + hb_itemPutC( pItem, "NVARCHAR" ); else hb_itemPutC( pItem, "Q" ); break; case HB_FT_MEMO: - hb_itemPutC( pItem, "M" ); + if( pField->uiFlags & HB_FF_UNICODE ) + hb_itemPutC( pItem, "NMEMO" ); + else + hb_itemPutC( pItem, "M" ); break; case HB_FT_IMAGE: @@ -2115,12 +2151,24 @@ static HB_ERRCODE adsGetValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem memset( pBuffer, ' ', u32Length ); u32RetVal = AE_SUCCESS; } -#ifdef ADS_USE_OEM_TRANSLATION -#if ADS_LIB_VERSION >= 900 - else if( hb_ads_bOEM && pField->uiTypeExtended != ADS_RAW && pField->uiTypeExtended != ADS_VARBINARY_FOX ) -#else - else if( hb_ads_bOEM && pField->uiTypeExtended != ADS_RAW ) +#if ADS_LIB_VERSION >= 1000 + else if( ( pField->uiFlags & HB_FF_UNICODE ) != 0 ) + { + u32RetVal = AdsGetFieldW( pArea->hTable, ADSFIELD( uiIndex ), ( WCHAR * ) pBuffer, &u32Length, ADS_NONE ); + if( u32RetVal != AE_SUCCESS ) + { + u32Length = pField->uiType == HB_FT_STRING ? pField->uiLen : 0; + memset( pBuffer, ' ', u32Length ); + } + else + { + hb_itemPutStrLenU16( pItem, HB_CDP_ENDIAN_LITTLE, ( HB_WCHAR * ) pBuffer, u32Length ); + break; + } + } #endif +#ifdef ADS_USE_OEM_TRANSLATION + else if( ( pField->uiFlags & HB_FF_BINARY ) == 0 ) { #if ADS_LIB_VERSION >= 600 u32RetVal = AdsGetFieldRaw( pArea->hTable, ADSFIELD( uiIndex ), pBuffer, &u32Length ); @@ -2333,7 +2381,6 @@ static HB_ERRCODE adsGetValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem case HB_FT_IMAGE: { UNSIGNED8 *pucBuf; - UNSIGNED32 u32Len; UNSIGNED16 u16Type; u32RetVal = AdsGetMemoDataType( pArea->hTable, ADSFIELD( uiIndex ), &u16Type ); @@ -2341,53 +2388,62 @@ static HB_ERRCODE adsGetValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem { hb_itemPutC( pItem, NULL ); } - else if( u16Type != ADS_BINARY && u16Type != ADS_IMAGE ) + else if( u16Type == ADS_BINARY || u16Type == ADS_IMAGE ) { - u32RetVal = AdsGetMemoLength( pArea->hTable, ADSFIELD( uiIndex ), &u32Len ); + u32RetVal = AdsGetBinaryLength( pArea->hTable, ADSFIELD( uiIndex ), &u32Length ); if( u32RetVal != AE_SUCCESS ) hb_itemPutC( pItem, NULL ); else { - if( u32Len > 0 ) - { - u32Len++; /* make room for NULL */ - pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Len ); - u32RetVal = AdsGetString( pArea->hTable, ADSFIELD( uiIndex ), pucBuf, &u32Len, ADS_NONE ); - if( u32RetVal != AE_SUCCESS ) - hb_itemPutC( pItem, NULL ); - else - { -#ifdef ADS_USE_OEM_TRANSLATION - char * szRet = hb_adsAnsiToOem( ( char * ) pucBuf, u32Len ); - hb_itemPutCL( pItem, szRet, u32Len ); - hb_adsOemAnsiFree( szRet ); -#else - hb_itemPutCL( pItem, ( char * ) pucBuf, u32Len ); -#endif - } - hb_xfree( pucBuf ); - } - else - hb_itemPutC( pItem, NULL ); - } - } - else - { - u32RetVal = AdsGetBinaryLength( pArea->hTable, ADSFIELD( uiIndex ), &u32Len ); - if( u32RetVal != AE_SUCCESS ) - hb_itemPutC( pItem, NULL ); - else - { - u32Len++; /* make room for NULL */ - pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Len ); - u32RetVal = AdsGetBinary( pArea->hTable, ADSFIELD( uiIndex ), 0, pucBuf, &u32Len ); + u32Length++; /* make room for NULL */ + pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Length ); + u32RetVal = AdsGetBinary( pArea->hTable, ADSFIELD( uiIndex ), 0, pucBuf, &u32Length ); if( u32RetVal != AE_SUCCESS ) { hb_xfree( pucBuf ); hb_itemPutC( pItem, NULL ); } else - hb_itemPutCLPtr( pItem, ( char * ) pucBuf, u32Len ); + hb_itemPutCLPtr( pItem, ( char * ) pucBuf, u32Length ); + } + } + else + { + u32RetVal = AdsGetMemoLength( pArea->hTable, ADSFIELD( uiIndex ), &u32Length ); + if( u32RetVal != AE_SUCCESS || u32Length == 0 ) + hb_itemPutC( pItem, NULL ); +#if ADS_LIB_VERSION >= 1000 + else if( ( pField->uiFlags & HB_FF_UNICODE ) != 0 ) + { + HB_WCHAR * pwBuffer = hb_xgrab( ( ++u32Length ) << 1 ); + u32RetVal = AdsGetStringW( pArea->hTable, ADSFIELD( uiIndex ), ( WCHAR * ) pwBuffer, &u32Length, ADS_NONE ); + if( u32RetVal != AE_SUCCESS ) + hb_itemPutC( pItem, NULL ); + else + hb_itemPutStrLenU16( pItem, HB_CDP_ENDIAN_LITTLE, pwBuffer, u32Length ); + hb_xfree( pwBuffer ); + } +#endif + else + { + u32Length++; /* make room for NULL */ + pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Length ); + u32RetVal = AdsGetString( pArea->hTable, ADSFIELD( uiIndex ), pucBuf, &u32Length, ADS_NONE ); + if( u32RetVal != AE_SUCCESS ) + hb_itemPutC( pItem, NULL ); + else + { +#ifdef ADS_USE_OEM_TRANSLATION + char * szRet = hb_adsAnsiToOem( ( char * ) pucBuf, u32Length ); + hb_itemPutCL( pItem, szRet, u32Length ); + hb_adsOemAnsiFree( szRet ); +#else + hb_itemPutCLPtr( pItem, ( char * ) pucBuf, u32Length ); + pucBuf = NULL; +#endif + } + if( pucBuf ) + hb_xfree( pucBuf ); } } hb_itemSetCMemo( pItem ); @@ -2492,7 +2548,7 @@ static HB_ERRCODE adsPutRec( ADSAREAP pArea, const HB_BYTE * pBuffer ) static HB_ERRCODE adsPutValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem ) { LPFIELD pField; - HB_USHORT uiCount; + HB_SIZE nLen; HB_BYTE * szText; HB_BOOL bTypeError = HB_TRUE; UNSIGNED32 u32RetVal = 0; @@ -2546,27 +2602,42 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem if( HB_IS_STRING( pItem ) ) { bTypeError = HB_FALSE; - uiCount = ( HB_USHORT ) hb_itemGetCLen( pItem ); - if( uiCount > pField->uiLen ) - uiCount = pField->uiLen; - -#ifdef ADS_USE_OEM_TRANSLATION - if( hb_ads_bOEM ) +#if ADS_LIB_VERSION >= 1000 + if( ( pField->uiFlags & HB_FF_UNICODE ) != 0 ) { -#if ADS_LIB_VERSION >= 600 - u32RetVal = AdsSetFieldRaw( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), uiCount ); -#else - char * pBuffer = hb_adsOemToAnsi( hb_itemGetCPtr( pItem ), uiCount ); - u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) pBuffer, uiCount ); - hb_adsOemAnsiFree( pBuffer ); -#endif + void * hString; + const HB_WCHAR * pwBuffer = hb_itemGetStrU16( pItem, HB_CDP_ENDIAN_LITTLE, + &hString, &nLen ); + if( nLen > ( HB_SIZE ) pField->uiLen ) + nLen = pField->uiLen; + u32RetVal = AdsSetStringW( pArea->hTable, ADSFIELD( uiIndex ), + ( WCHAR * ) pwBuffer, nLen ); + hb_strfree( hString ); } else #endif { - u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), uiCount ); - } + nLen = hb_itemGetCLen( pItem ); + if( nLen > ( HB_SIZE ) pField->uiLen ) + nLen = pField->uiLen; +#ifdef ADS_USE_OEM_TRANSLATION + if( hb_ads_bOEM ) + { +#if ADS_LIB_VERSION >= 600 + u32RetVal = AdsSetFieldRaw( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), nLen ); +#else + char * pBuffer = hb_adsOemToAnsi( hb_itemGetCPtr( pItem ), nLen ); + u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) pBuffer, nLen ); + hb_adsOemAnsiFree( pBuffer ); +#endif + } + else +#endif + { + u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), nLen ); + } + } } break; @@ -2632,40 +2703,49 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem case HB_FT_IMAGE: if( HB_IS_STRING( pItem ) ) { - HB_SIZE ulLen; - bTypeError = HB_FALSE; - ulLen = hb_itemGetCLen( pItem ); + nLen = hb_itemGetCLen( pItem ); - /* ToninhoFwi - 09/12/2006 - In the previous code ulLen was limited to 0xFFFF + /* ToninhoFwi - 09/12/2006 - In the previous code nLen was limited to 0xFFFF so, I comment it, because ADS support up to 4Gb in memo/binary/image fields. Advantage documentations says that we need use AdsSetBinary in binary/image fields. I tested these special fields with AdsSetString() and it works, but is a little bit slower to save big image file in the fields, so I keep AdsSetString() only for commom memo fields and AdsSetBinary() for the others. */ - if( pField->uiTypeExtended != ADS_BINARY && pField->uiTypeExtended != ADS_IMAGE ) + if( pField->uiTypeExtended == ADS_BINARY || pField->uiTypeExtended == ADS_IMAGE ) + { + u32RetVal = AdsSetBinary( pArea->hTable, ADSFIELD( uiIndex ), + pField->uiTypeExtended, + ( UNSIGNED32 ) nLen, 0, + ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), + ( UNSIGNED32 ) nLen ); + } +#if ADS_LIB_VERSION >= 1000 + else if( ( pField->uiFlags & HB_FF_UNICODE ) != 0 ) + { + void * hString; + const HB_WCHAR * pwBuffer = hb_itemGetStrU16( pItem, HB_CDP_ENDIAN_LITTLE, + &hString, &nLen ); + u32RetVal = AdsSetStringW( pArea->hTable, ADSFIELD( uiIndex ), + ( WCHAR * ) pwBuffer, nLen ); + hb_strfree( hString ); + } +#endif + else { #ifdef ADS_USE_OEM_TRANSLATION - char * szRet = hb_adsOemToAnsi( hb_itemGetCPtr( pItem ), ulLen ); + char * szRet = hb_adsOemToAnsi( hb_itemGetCPtr( pItem ), nLen ); u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) szRet, - ( UNSIGNED32 ) ulLen ); + ( UNSIGNED32 ) nLen ); hb_adsOemAnsiFree( szRet ); #else u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), - ( UNSIGNED32 ) ulLen ); + ( UNSIGNED32 ) nLen ); #endif } - else - { - u32RetVal = AdsSetBinary( pArea->hTable, ADSFIELD( uiIndex ), - pField->uiTypeExtended, - ( UNSIGNED32 ) ulLen, 0, - ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), - ( UNSIGNED32 ) ulLen ); - } } break; } @@ -2842,6 +2922,7 @@ static HB_ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo ) HB_USHORT uiCount; LPFIELD pField; const char * cType; + HB_BOOL fUnicode; HB_TRACE(HB_TR_DEBUG, ("adsCreate(%p, %p)", pArea, pCreateInfo)); @@ -2849,6 +2930,7 @@ static HB_ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo ) pArea->szDataFileName = hb_strdup( ( char * ) pCreateInfo->abName ); + fUnicode = HB_FALSE; pArea->maxFieldLen = 0; /* uiLen = length of buffer for all field definition info times number of fields. @@ -2885,6 +2967,11 @@ static HB_ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo ) case HB_FT_STRING: if( pField->uiTypeExtended == ADS_RAW ) cType = "Raw"; + else if( pField->uiFlags & HB_FF_UNICODE ) + { + cType = "NChar"; + fUnicode = HB_TRUE; + } #ifdef ADS_CISTRING else if( pField->uiTypeExtended == ADS_CISTRING ) cType = "CICharacter"; @@ -2954,12 +3041,23 @@ static HB_ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo ) case HB_FT_VARLENGTH: if( pField->uiFlags & HB_FF_BINARY ) cType = "VarBinary"; + else if( pField->uiFlags & HB_FF_UNICODE ) + { + fUnicode = HB_TRUE; + cType = "NVarChar"; + } else cType = "VarChar"; break; case HB_FT_MEMO: - cType = "Memo"; + if( pField->uiFlags & HB_FF_UNICODE ) + { + cType = "NMemo"; + fUnicode = HB_TRUE; + } + else + cType = "Memo"; break; case HB_FT_BLOB: @@ -3026,6 +3124,8 @@ static HB_ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo ) } *ucfieldPtr = '\0'; + if( fUnicode ) + pArea->maxFieldLen <<= 1; if( pArea->maxFieldLen < 24 ) pArea->maxFieldLen = 24; @@ -3267,7 +3367,7 @@ static HB_ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) UNSIGNED16 usBufLen, usType, usDecimals; DBFIELDINFO dbFieldInfo; char szAlias[ HB_RDD_MAX_ALIAS_LEN + 1 ], * szFile; - HB_BOOL fDictionary = HB_FALSE; + HB_BOOL fDictionary = HB_FALSE, fUnicode = HB_FALSE; HB_TRACE(HB_TR_DEBUG, ("adsOpen(%p)", pArea)); @@ -3517,14 +3617,36 @@ static HB_ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) dbFieldInfo.uiType = HB_FT_IMAGE; dbFieldInfo.uiFlags = HB_FF_BINARY; break; + +#if ADS_LIB_VERSION >= 1000 + case ADS_NCHAR: + dbFieldInfo.uiType = HB_FT_STRING; + dbFieldInfo.uiFlags = HB_FF_UNICODE; + fUnicode = HB_TRUE; + break; + + case ADS_NVARCHAR: + dbFieldInfo.uiType = HB_FT_VARLENGTH; + dbFieldInfo.uiFlags = HB_FF_UNICODE; + fUnicode = HB_TRUE; + break; + + case ADS_NMEMO: + dbFieldInfo.uiType = HB_FT_MEMO; + dbFieldInfo.uiFlags = HB_FF_UNICODE; + fUnicode = HB_TRUE; + break; +#endif + default: + return HB_FAILURE; } if( SELF_ADDFIELD( ( AREAP ) pArea, &dbFieldInfo ) == HB_FAILURE ) - { return HB_FAILURE; - } } + if( fUnicode ) + pArea->maxFieldLen <<= 1; if( pArea->maxFieldLen < 24 ) pArea->maxFieldLen = 24; diff --git a/harbour/include/hbapirdd.h b/harbour/include/hbapirdd.h index 1bf5d54ba6..322f61b345 100644 --- a/harbour/include/hbapirdd.h +++ b/harbour/include/hbapirdd.h @@ -121,6 +121,7 @@ HB_EXTERN_BEGIN #define HB_FF_AUTOINC 0x0008 /* Column is autoincrementing */ #define HB_FF_COMPRESSED 0x0010 /* Column is compressed */ #define HB_FF_ENCRYPTED 0x0020 /* Column is encrypted */ +#define HB_FF_UNICODE 0x0040 /* Column stores Unicode strings */