diff --git a/ChangeLog.txt b/ChangeLog.txt index 5b82926aa5..55e06972ef 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,31 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2016-08-10 20:12 UTC+0300 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) + * contrib/rddads/ads.ch + + 64bit server type constants included + + * include/dbinfo.ch + * contrib/rddsql/hbrddsql.h + * contrib/rddsql/rddsql.hbc + - contrib/rddsql/hbrddsql.ch + * definitions of SQL related RDDI_*, DBI_* constants moved from RDDSQL + to core code + * include/dbinfo.ch + * contrib/rddsql/sqlbase.c + * RDDI_NEWID renamed to more informative RDDI_INSERTID + + * contrib/rddads/ads1.c + * contrib/rddads/adsfunc.c + * contrib/rddads/rddads.h + + RDDI_CONNECT, RDDI_DISCONNECT implemented. RDDINFO() can be used instead + of RDD specific AdsConnect*() calls + + other SQL related RDDINFO(), DBINFO() capabilities implemented + + DBUSEAREA() accepts prefixes "SQL:" and "TABLE:" to indicate if + given table name should be treated as SQL query or table file name. + If these prefixes are omitted, function parameter is treated as table + file name except in case it begins with "SELECT " (compatibility). + 2016-07-18 20:32 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbssl/hbssl.hbx * contrib/hbssl/pem.c diff --git a/contrib/rddads/ads.ch b/contrib/rddads/ads.ch index c22914d115..3e6f8cbcf9 100644 --- a/contrib/rddads/ads.ch +++ b/contrib/rddads/ads.ch @@ -120,6 +120,8 @@ #define ADS_MGMT_WIN9X_SERVER 4 #define ADS_MGMT_NETWARE5_OR_NEWER_SERVER 5 #define ADS_MGMT_LINUX_SERVER 6 +#define ADS_MGMT_NT_SERVER_64_BIT 7 +#define ADS_MGMT_LINUX_SERVER_64_BIT 8 /* ACE handle types */ #define ADS_CONNECTION 1 diff --git a/contrib/rddads/ads1.c b/contrib/rddads/ads1.c index 8c520de600..9b9d3c7591 100644 --- a/contrib/rddads/ads1.c +++ b/contrib/rddads/ads1.c @@ -57,6 +57,7 @@ #include "hbapilng.h" #include "hbdate.h" #include "hbset.h" +#include "hbstack.h" #include "rddsys.ch" #include "rddads.h" @@ -74,6 +75,19 @@ static HB_USHORT s_uiRddIdADSVFP = ( HB_USHORT ) -1; static RDDFUNCS adsSuper; +#define ERROR_BUFFER_LEN 512 + +typedef struct _RDDADSDATA +{ + UNSIGNED32 ulError; + UNSIGNED32 ulInsertID; + UNSIGNED32 ulAffectedRows; + UNSIGNED8 szError[ ERROR_BUFFER_LEN + 1 ]; + char * szQuery; +} RDDADSDATA, * LPRDDADSDATA; + +#define RDDADSNODE_DATA( r ) ( ( LPRDDADSDATA ) hb_stackGetTSD( ( PHB_TSD ) ( r )->lpvCargo ) ) + /* * -- HELPER FUNCTIONS -- @@ -2949,6 +2963,11 @@ static HB_ERRCODE adsClose( ADSAREAP pArea ) { HB_TRACE( HB_TR_DEBUG, ( "adsClose(%p)", pArea ) ); + if( pArea->szQuery ) + { + hb_xfree( pArea->szQuery ); + pArea->szQuery = NULL; + } return hb_adsCloseCursor( pArea ); } @@ -3438,8 +3457,14 @@ static HB_ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) hTable = pArea->hTable; hStatement = pArea->hStatement; } - else if( szFile && hb_strnicmp( szFile, "SELECT ", 7 ) == 0 ) + else if( szFile && ( ( hb_strnicmp( szFile, "SELECT ", 7 ) == 0 ) || + ( hb_strnicmp( szFile, "SQL:", 4 ) == 0 ) ) ) { + if( hb_strnicmp( szFile, "SQL:", 4 ) == 0 ) + szFile += 4; + + pArea->szQuery = hb_strdup( szFile ); + u32RetVal = AdsCreateSQLStatement( hConnection, &hStatement ); if( u32RetVal == AE_SUCCESS ) { @@ -3475,18 +3500,21 @@ static HB_ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) return HB_FAILURE; } } - else + else /* if( hb_strnicmp( szFile, "TABLE:", 6 ) == 0 ) */ { PHB_ITEM pError = NULL; HB_BOOL fRetry; + if( szFile && ( hb_strnicmp( szFile, "TABLE:", 6 ) == 0 ) ) + szFile += 6; + /* Use an Advantage Data Dictionary * if fDictionary was set for this connection */ do { u32RetVal = AdsOpenTable( hConnection, - ( UNSIGNED8 * ) HB_UNCONST( pOpenInfo->abName ), + ( UNSIGNED8 * ) HB_UNCONST( szFile ), ( UNSIGNED8 * ) HB_UNCONST( pOpenInfo->atomAlias ), ( fDictionary ? ADS_DEFAULT : ( UNSIGNED16 ) pArea->iFileType ), ( UNSIGNED16 ) hb_ads_iCharType, @@ -5185,7 +5213,28 @@ static HB_ERRCODE adsRename( LPRDDNODE pRDD, PHB_ITEM pItemTable, PHB_ITEM pItem return HB_FAILURE; } -#define adsInit NULL +static void adsTSDRelease( void * cargo ) +{ + LPRDDADSDATA pData = ( LPRDDADSDATA ) cargo; + + if( pData->szQuery ) + hb_xfree( pData->szQuery ); +} + +static HB_ERRCODE adsInit( LPRDDNODE pRDD ) +{ + PHB_TSD pTSD; + + pTSD = ( PHB_TSD ) hb_xgrab( sizeof( HB_TSD ) ); + HB_TSD_INIT( pTSD, sizeof( RDDADSDATA ), NULL, adsTSDRelease ); + pRDD->lpvCargo = ( void * ) pTSD; + + if( ISSUPER_INIT( pRDD ) ) + return SUPER_INIT( pRDD ); + else + return HB_SUCCESS; +} + static HB_ERRCODE adsExit( LPRDDNODE pRDD ) { @@ -5210,9 +5259,17 @@ static HB_ERRCODE adsExit( LPRDDNODE pRDD ) } } - /* free pRDD->lpvCargo if necessary */ + if( pRDD->lpvCargo ) + { + hb_stackReleaseTSD( ( PHB_TSD ) pRDD->lpvCargo ); + hb_xfree( pRDD->lpvCargo ); + pRDD->lpvCargo = NULL; + } - return HB_SUCCESS; + if( ISSUPER_EXIT( pRDD ) ) + return SUPER_EXIT( pRDD ); + else + return HB_SUCCESS; } @@ -5234,6 +5291,71 @@ static HB_ERRCODE adsRddInfo( LPRDDNODE pRDD, HB_USHORT uiIndex, HB_ULONG ulConn HB_ADS_PUTCONNECTION( pItem, hOldConnection ); break; } + + case RDDI_CONNECT: + { + ADSHANDLE hConnect = 0; + UNSIGNED32 u32RetVal; + LPRDDADSDATA pData = RDDADSNODE_DATA( pRDD ); + + if( HB_IS_ARRAY( pItem ) ) + { +#if ADS_LIB_VERSION >= 600 + u32RetVal = AdsConnect60( ( UNSIGNED8 * ) HB_UNCONST( hb_arrayGetCPtr( pItem, 1 ) ) /* pucServerPath */, + ( UNSIGNED16 ) hb_arrayGetNI( pItem, 2 ) /* usServerTypes */, + ( UNSIGNED8 * ) HB_UNCONST( hb_arrayGetCPtr( pItem, 3 ) ) /* pucUserName */, + ( UNSIGNED8 * ) HB_UNCONST( hb_arrayGetCPtr( pItem, 4 ) ) /* pucPassword */, + ( UNSIGNED32 ) hb_arrayGetNL( pItem, 5 ) /* ulOptions */, + &hConnect ); + +#else + u32RetVal = AdsConnect( ( UNSIGNED8 * ) HB_UNCONST( hb_itemGetCPtr( pItem ) ), &hConnect ); +#endif + } + else + { + u32RetVal = AdsConnect( ( UNSIGNED8 * ) HB_UNCONST( hb_itemGetCPtr( pItem ) ), &hConnect ); + } + + if( u32RetVal == AE_SUCCESS ) + { + hb_ads_setConnection( hConnect ); /* set new default */ + pData->ulError = pData->ulInsertID = pData->ulAffectedRows = 0; + pData->szError[ 0 ] = '\0'; + HB_ADS_PUTCONNECTION( pItem, hConnect ); + } + else + { + UNSIGNED16 usLen = ERROR_BUFFER_LEN; + + pData->ulError = u32RetVal; + AdsGetLastError( &u32RetVal, pData->szError, &usLen ); + pData->szError[ usLen ] = '\0'; + HB_ADS_PUTCONNECTION( pItem, 0 ); + } + break; + } + + case RDDI_DISCONNECT: + { + ADSHANDLE hConnect = HB_ADS_GETCONNECTION( pItem ); + + /* NOTE: Only allow disconnect of 0 if explicitly passed. + The thread default connection handle might be 0 if caller + accidentally disconnects twice. */ + + if( ( hConnect != 0 || HB_IS_NUMERIC( pItem ) ) && + AdsDisconnect( hConnect ) == AE_SUCCESS ) + { + hb_ads_clrConnection( hConnect ); + hb_itemPutL( pItem, HB_TRUE ); + } + else + hb_itemPutL( pItem, HB_FALSE ); + + break; + } + case RDDI_ISDBF: hb_itemPutL( pItem, adsGetFileType( pRDD->rddID ) != ADS_ADT ); break; @@ -5271,6 +5393,89 @@ static HB_ERRCODE adsRddInfo( LPRDDNODE pRDD, HB_USHORT uiIndex, HB_ULONG ulConn break; } + case RDDI_ERRORNO: + { + LPRDDADSDATA pData = RDDADSNODE_DATA( pRDD ); + hb_itemPutNL( pItem, ( unsigned long ) pData->ulError ); + break; + } + + case RDDI_ERROR: + { + LPRDDADSDATA pData = RDDADSNODE_DATA( pRDD ); + hb_itemPutC( pItem, ( char * ) pData->szError ); + break; + } + + case RDDI_INSERTID: + { + LPRDDADSDATA pData = RDDADSNODE_DATA( pRDD ); + hb_itemPutNL( pItem, ( unsigned long ) pData->ulInsertID ); + break; + } + + case RDDI_AFFECTEDROWS: + { + LPRDDADSDATA pData = RDDADSNODE_DATA( pRDD ); + hb_itemPutNL( pItem, ( unsigned long ) pData->ulAffectedRows ); + break; + } + + case RDDI_EXECUTE: + { + + LPRDDADSDATA pData = RDDADSNODE_DATA( pRDD ); + ADSHANDLE hConnect = ulConnect ? ( ADSHANDLE ) ulConnect : hb_ads_getConnection(); + ADSHANDLE hStatement = 0; + UNSIGNED32 u32RetVal; + + pData->ulError = pData->ulInsertID = pData->ulAffectedRows = 0; + pData->szError[ 0 ] = '\0'; + + u32RetVal = AdsCreateSQLStatement( hConnect, &hStatement ); + if( u32RetVal == AE_SUCCESS ) + { + ADSHANDLE hCursor = 0; + + AdsStmtSetTableType( hStatement, adsGetFileType( pRDD->rddID ) ); + + u32RetVal = AdsExecuteSQLDirect( hStatement, ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ), &hCursor ); + if( u32RetVal == AE_SUCCESS ) + { + if( AdsGetLastAutoinc( hStatement, &u32RetVal ) == AE_SUCCESS ) + pData->ulInsertID = u32RetVal; + + if( AdsGetRecordCount( hStatement, ADS_IGNOREFILTERS, &u32RetVal ) == AE_SUCCESS ) + pData->ulAffectedRows = u32RetVal; + + if( hCursor ) + AdsCloseTable( hCursor ); + + u32RetVal = AE_SUCCESS; + } + else + { + UNSIGNED16 usLen = ERROR_BUFFER_LEN; + + pData->ulError = u32RetVal; + AdsGetLastError( &u32RetVal, pData->szError, &usLen ); + pData->szError[ usLen ] = '\0'; + + } + AdsCloseSQLStatement( hStatement ); + } + else + { + UNSIGNED16 usLen = ERROR_BUFFER_LEN; + + pData->ulError = u32RetVal; + AdsGetLastError( &u32RetVal, pData->szError, &usLen ); + pData->szError[ usLen ] = '\0'; + } + hb_itemPutL( pItem, u32RetVal == AE_SUCCESS ); + break; + } + default: return SUPER_RDDINFO( pRDD, uiIndex, ulConnect, pItem ); } diff --git a/contrib/rddads/adsfunc.c b/contrib/rddads/adsfunc.c index 87f1f74b7f..090fe1c293 100644 --- a/contrib/rddads/adsfunc.c +++ b/contrib/rddads/adsfunc.c @@ -199,7 +199,7 @@ void hb_ads_setConnection( ADSHANDLE hConnect ) HB_ADS_CONN_DATA->hConnect = hConnect; } -static void hb_ads_clrConnection( ADSHANDLE hConnect ) +void hb_ads_clrConnection( ADSHANDLE hConnect ) { PHB_ADSDATA pAdsData = HB_ADS_CONN_DATA; diff --git a/contrib/rddads/rddads.h b/contrib/rddads/rddads.h index 61e9f2fa0f..0ec8d157c0 100644 --- a/contrib/rddads/rddads.h +++ b/contrib/rddads/rddads.h @@ -149,6 +149,7 @@ typedef struct _ADSAREA_ ADSHANDLE hTable; ADSHANDLE hOrdCurrent; ADSHANDLE hStatement; + char * szQuery; } ADSAREA; typedef ADSAREA * ADSAREAP; @@ -186,6 +187,7 @@ extern HB_BOOL hb_ads_bTestRecLocks; extern ADSHANDLE hb_ads_getConnection( void ); extern ADSHANDLE hb_ads_defConnection( ADSHANDLE hConnect, const char * szName ); +extern void hb_ads_clrConnection( ADSHANDLE hConnect ); extern void hb_ads_setConnection( ADSHANDLE hConnect ); extern int hb_ads_getIndexPageSize( void ); extern void hb_ads_setIndexPageSize( int iIndexPageSize ); diff --git a/contrib/rddsql/hbrddsql.ch b/contrib/rddsql/hbrddsql.ch deleted file mode 100644 index 43893035b6..0000000000 --- a/contrib/rddsql/hbrddsql.ch +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SQL Database Driver include file - * - * Copyright 2009 Mindaugas Kavaliauskas - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING.txt. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA (or visit the web site https://www.gnu.org/). - * - * As a special exception, the Harbour Project gives permission for - * additional uses of the text contained in its release of Harbour. - * - * The exception is that, if you link the Harbour libraries with other - * files to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the Harbour library code into it. - * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. - * - * This exception applies only to the code released by the Harbour - * Project under the name Harbour. If you copy code from other - * Harbour Project or Free Software Foundation releases into a copy of - * Harbour, as the General Public License permits, the exception does - * not apply to the code that you add in this way. To avoid misleading - * anyone as to the status of such modified files, you must delete - * this exception notice from them. - * - * If you write modifications of your own for Harbour, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. - * - */ - -/* NOTE: This file is also used by C code. */ - -#ifndef HB_RDDSQL_CH_ -#define HB_RDDSQL_CH_ - -/* New ...INFO_ constants */ -#define DBI_QUERY 1001 - -#define RDDI_CONNECT 1001 -#define RDDI_DISCONNECT 1002 -#define RDDI_EXECUTE 1003 -#define RDDI_ERROR 1004 -#define RDDI_ERRORNO 1005 -#define RDDI_NEWID 1006 -#define RDDI_AFFECTEDROWS 1007 -#define RDDI_QUERY 1008 - -#endif diff --git a/contrib/rddsql/hbrddsql.h b/contrib/rddsql/hbrddsql.h index 30b335655a..373e73079a 100644 --- a/contrib/rddsql/hbrddsql.h +++ b/contrib/rddsql/hbrddsql.h @@ -53,7 +53,6 @@ #include "hbapierr.h" #include "hbapilng.h" #include "hbapi.h" -#include "hbrddsql.ch" /* ==================================================================== diff --git a/contrib/rddsql/rddsql.hbc b/contrib/rddsql/rddsql.hbc index 08994ac96d..c5780b9f51 100644 --- a/contrib/rddsql/rddsql.hbc +++ b/contrib/rddsql/rddsql.hbc @@ -2,6 +2,4 @@ description=RDDSQL core RDD incpaths=. -headers=hbrddsql.ch - libs=${_HB_DYNPREF}${hb_name}${_HB_DYNSUFF} diff --git a/contrib/rddsql/sqlbase.c b/contrib/rddsql/sqlbase.c index 6edf69260c..92736cd3f9 100644 --- a/contrib/rddsql/sqlbase.c +++ b/contrib/rddsql/sqlbase.c @@ -1070,7 +1070,7 @@ static HB_ERRCODE sqlbaseRddInfo( LPRDDNODE pRDD, HB_USHORT uiIndex, HB_ULONG ul hb_itemPutC( pItem, s_szQuery ); return HB_SUCCESS; - case RDDI_NEWID: + case RDDI_INSERTID: hb_itemCopy( pItem, s_pItemNewID ); return HB_SUCCESS; diff --git a/include/dbinfo.ch b/include/dbinfo.ch index cc908ebfe1..b3e0f137b7 100644 --- a/include/dbinfo.ch +++ b/include/dbinfo.ch @@ -107,6 +107,16 @@ #define RDDI_DECIMALS 46 /* Get/Set default number of decimal places for numeric fields if it's undefined */ #define RDDI_SETHEADER 47 /* DBF header updating modes */ +/* SQL */ +#define RDDI_CONNECT 61 /* connect to database */ +#define RDDI_DISCONNECT 62 /* disconnect from database */ +#define RDDI_EXECUTE 63 /* execute SQL statement */ +#define RDDI_ERROR 64 /* error number */ +#define RDDI_ERRORNO 65 /* error description */ +#define RDDI_INSERTID 66 /* last auto insert ID */ +#define RDDI_AFFECTEDROWS 67 /* number of affected rows after UPDATE */ +#define RDDI_QUERY 68 /* last executed query */ + /* Constants for SELF_ORDINFO () */ @@ -306,6 +316,8 @@ #define DBI_RM_COUNT 158 /* number of records set in record map */ #define DBI_RM_HANDLE 159 /* get/set record map filter handle */ +#define DBI_QUERY 170 /* if area represents result of a query, obtain expression of this query */ + /* BLOB support - definitions for internal use by blob.ch */ #define DBI_BLOB_DIRECT_EXPORT 201 #define DBI_BLOB_DIRECT_GET 202