2021-03-31 23:43 UTC+0200 Aleksander Czajczynski (hb fki.pl)

* contrib/hbpgsql/postgres.c
    ! guard PQEXECPARAMS() wrapper from generating unrecoverable error
      on empty parameter array "hb_xgrab requested to allocate zero bytes"

  * contrib/hbpgsql/tpostgre.prg
    ! corrected buggy parameter order in TPQserver():Query()

    * make TPQQuery, TPQRow classes more aware of NIL to NULL conversions,
      added support for inserting and updating empty xBase date value
      should fix issue #234, oRow:FieldPut( <n>, NIL ) also looks good
This commit is contained in:
Aleksander Czajczynski
2021-03-31 23:43:52 +02:00
parent ff3a726edf
commit 8a8575609a
3 changed files with 54 additions and 24 deletions

View File

@@ -7,6 +7,18 @@
Entries may not always be in chronological/commit order.
See license at the end of file. */
2021-03-31 23:43 UTC+0200 Aleksander Czajczynski (hb fki.pl)
* contrib/hbpgsql/postgres.c
! guard PQEXECPARAMS() wrapper from generating unrecoverable error
on empty parameter array "hb_xgrab requested to allocate zero bytes"
* contrib/hbpgsql/tpostgre.prg
! corrected buggy parameter order in TPQserver():Query()
* make TPQQuery, TPQRow classes more aware of NIL to NULL conversions,
added support for inserting and updating empty xBase date value
should fix issue #234, oRow:FieldPut( <n>, NIL ) also looks good
2021-03-31 21:26 UTC+0200 Aleksander Czajczynski (hb fki.pl)
* contrib/hbpgsql/hbpgsql.hbx
* contrib/hbpgsql/postgres.c

View File

@@ -688,16 +688,22 @@ HB_FUNC( PQEXECPARAMS )
if( conn && aParam )
{
int n = ( int ) hb_arrayLen( aParam );
int i;
const char ** paramvalues = ( const char ** ) hb_xgrab( sizeof( char * ) * n );
if( ! n )
hb_PGresult_ret( PQexec( conn, hb_parcx( 2 ) ) );
else
{
int i;
for( i = 0; i < n; ++i )
paramvalues[ i ] = hb_arrayGetCPtr( aParam, i + 1 );
const char ** paramvalues = ( const char ** ) hb_xgrab( sizeof( char * ) * n );
hb_PGresult_ret( PQexecParams( conn, hb_parcx( 2 ), n, NULL, paramvalues, NULL, NULL, hb_parnidef( 4, 1 ) ) );
for( i = 0; i < n; ++i )
paramvalues[ i ] = hb_arrayGetCPtr( aParam, i + 1 );
hb_xfree( ( void * ) paramvalues );
hb_PGresult_ret( PQexecParams( conn, hb_parcx( 2 ), n, NULL, paramvalues, NULL, NULL, hb_parnidef( 4, 1 ) ) );
hb_xfree( ( void * ) paramvalues );
}
}
else
hb_errRT_BASE( EG_ARG, 2020, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );

View File

@@ -194,7 +194,7 @@ METHOD Query( cQuery, lNull ) CLASS TPQserver
lNull := ::lNull
ENDIF
RETURN TPQQuery():New( ::pDB, cQuery, ::lAllCols, ::Schema, lNull )
RETURN TPQQuery():New( ::pDB, cQuery, ::lAllCols, ::Schema,, lNull )
METHOD TableExists( cTable ) CLASS TPQserver
@@ -882,7 +882,7 @@ METHOD Append( oRow ) CLASS TPQquery
LOCAL res
LOCAL lChanged := .F.
LOCAL aParams := {}
LOCAL nParams := 0
LOCAL xParam
::SetKey()
@@ -893,21 +893,28 @@ METHOD Append( oRow ) CLASS TPQquery
FOR i := 1 TO oRow:FCount()
IF ::lAllCols .OR. oRow:Changed( i )
lChanged := .T.
cQuery += oRow:FieldName( i ) + ","
IF ! ( xParam := ValueToString( oRow:FieldGet( i ) ) ) == NIL
AAdd( aParams, xParam )
cQuery += oRow:FieldName( i ) + ","
ENDIF
ENDIF
NEXT
cQuery := hb_StrShrink( cQuery ) + ") VALUES ("
FOR i := 1 TO oRow:FCount()
IF ::lAllCols .OR. oRow:Changed( i )
nParams++
cQuery += "$" + hb_ntos( nParams ) + ","
AAdd( aParams, ValueToString( oRow:FieldGet( i ) ) )
ENDIF
NEXT
cQuery := hb_StrShrink( cQuery ) + ")"
IF lChanged .AND. Len( aParams ) == 0
/*
* Edge case here, adding a row filled with NULL values only,
* should add at least one field to conform with SQL syntax.
* This is possible with no primary key and/or when default
* values provided in table schema.
*/
cQuery := cQuery + oRow:FieldName( 1 ) + ") VALUES (NULL)"
ELSE
cQuery := hb_StrShrink( cQuery ) + ") VALUES ("
FOR i := 1 TO Len( aParams )
cQuery += "$" + hb_ntos( i ) + ","
NEXT
cQuery := hb_StrShrink( cQuery ) + ")"
ENDIF
IF lChanged
res := PQexecParams( ::pDB, cQuery, aParams )
@@ -938,6 +945,7 @@ METHOD Update( oRow ) CLASS TPQquery
LOCAL lChanged := .F.
LOCAL aParams := {}
LOCAL nParams := 0
LOCAL xParam
::SetKey()
@@ -962,9 +970,13 @@ METHOD Update( oRow ) CLASS TPQquery
FOR i := 1 TO oRow:FCount()
IF ::lAllCols .OR. oRow:Changed( i )
lChanged := .T.
nParams++
cQuery += oRow:FieldName( i ) + " = $" + hb_ntos( nParams ) + ","
AAdd( aParams, ValueToString( oRow:FieldGet( i ) ) )
IF ( xParam := ValueToString( oRow:FieldGet( i ) ) ) == NIL
cQuery += oRow:FieldName( i ) + " = NULL,"
ELSE
nParams++
cQuery += oRow:FieldName( i ) + " = $" + hb_ntos( nParams ) + ","
AAdd( aParams, xParam )
ENDIF
ENDIF
NEXT
@@ -1316,7 +1328,7 @@ STATIC FUNCTION ValueToString( xField )
SWITCH ValType( xField )
CASE "C"
CASE "M" ; RETURN xField
CASE "D" ; RETURN DToS( xField )
CASE "D" ; RETURN IIF( Empty( xField ), NIL, DToS( xField ) )
CASE "N" ; RETURN hb_ntos( xField )
CASE "L" ; RETURN iif( xField, "t", "f" )
ENDSWITCH