XSharpPublic icon indicating copy to clipboard operation
XSharpPublic copied to clipboard

COPY TO ARRAY problems II

Open Karl1155 opened this issue 4 years ago • 0 comments

don´t know if the mentioned problems have already been fixed ...

  • The func __BuildFieldList() uses XSharp.VFP.Functions.ALen() instead of XSharp.Rt.Functions.ALen() Without the changes - see the comments in the modified __BuildFieldList() code - an InvalidCastException is thrown.

  • The COPY to ARRAY command is translated to a DbCopyToArray() call. But the order of the written DbCopyToArray() parameters doesn´t work - see the comments in the sample code.

  • It´s possible to declare LIKE and EXCEPT fields, but currently both are ignored.

To make the COPY TO ARRAY command - at least partially - work , i modified the result pattern. ( see the #define USE_THIS_COPY_TO_ARRAY_COMMAND )

Using the modified command something like:

COPY TO ARRAY aResult1 FOR a->Last = "G" results no longer in:

aResult1 := DbCopyToArray( { }, NULL_STRING , NULL_STRING , {||a->Last="G"} , , , , .F. , .F. ) but in this code:

aResult1 := DbCopyToArray( { }, {||a->Last="G"} , , , , .F. , .F. , NULL_STRING , NULL_STRING )

regards Karl-Heinz

//  2.9.1.1 build + Fox dialect 
//    
//  /Memvar+ /ppo+
    
USING System.Collections.Generic 
USING XSharp.RDD.Support

// #define USE_THIS_COPY_TO_ARRAY_COMMAND 

#ifdef USE_THIS_COPY_TO_ARRAY_COMMAND

#command COPY TO ARRAY <arrayName> [FIELDS <f1> [,<fn> ] ]              ;
         [LIKE <%include%>] [EXCEPT <%exclude%> ]                       ;
         [FOR <FOR>]                                                    ;
         [WHILE <WHILE>]                                                ;
         [NEXT <NEXT>]                                                  ;
         [RECORD <rec>]                                                 ;
         [<rest:REST>]                                                  ;
         [<noopt: NOOPTIMIZE>]                                          ;
         [ALL]                                                          ;
                                                                        ;
      => <arrayName> := DbCopyToArray(                                  ;
                        {<(f1)>[, <(fn)> ]},     						;
                        <{FOR}>, <{WHILE}>, <NEXT>, <rec>, <.rest.>,    ;
                        <.noopt.> , #<include>, #<exclude>              ;
                        )
#endif  

FUNCTION Start( ) AS VOID
LOCAL cPfad, cDbf AS STRING 
LOCAL i AS DWORD 
LOCAL aFields, aValues AS ARRAY  
LOCAL dDate AS date 
	
  
//  ? RddSetDefault() // "DBFVFP"
    
    cPfad := "D:\TEST\" 

	cDBF := cPfad + "FooArray" 
	
	dDate := Today()
	
 	aFields := { { "LAST" , "C" , 10 , 0 } , { "FIRST" , "C" , 10 , 0 } , { "DATE" , "D" , 8 , 0 } } 
		
    // -------------------
	
	DbCreate( cDBF , AFields)
	DbUseArea( ,,cDBF )
	
	aValues := { "G1" , "A1" , "G2" , "G3" , "C1" , "D3" , "E56" , "G45"} 
	
	FOR i := 1 TO ALen ( aValues )  
		
		DbAppend() 
		
		FieldPut ( 1 , aValues [ i ] ) 		
		FieldPut ( 2 , "First" + NTrim ( i ) ) 
		FieldPut ( 3 , dDate ++ ) 
		
	NEXT 		       
	
	DbCloseArea() 
	
	DbUseArea ( ,, cDbf )
	
// -------------		

	PRIVATE aResult1  // yes, this works ;-)
//	Dimension aResult1(1)  
	
// ----------------------------------

COPY TO ARRAY aResult1 FOR a->Last = "G" 

? IIF ( aResult1 IS __FOXARRAY , "aResult1 contains a FoxArray" , "aResult1 contains no FoxArray" )	 
?
	
//	
// The - unchanged - command is translated to: 
//    aResult1 := DbCopyToArray( {  }, NULL_STRING , NULL_STRING , {||a->Last="G"} , ,  ,  , .F. , .F. )
// but the DbCopyToArray() signature is:
//    FUNCTION DbCopyToArray(aFieldList, cbForCondition, cbWhileCondition, nNext,nRecord, lRest, lNoOptimize) AS ARRAY CLIPPER
          
// This parameter order gives the expected result.    
//	aResult1 := DbCopyToArray( {}, {||_Field->Last="G"} ) // <----------
 
// ------------------------------

// DbGoTop()	
// COPY TO ARRAY aResult1 fields LAST NEXT 3

//
// The -unchanged- command is translated to: 
//   aResult1 := DbCopyToArray( { "LAST" }, NULL_STRING , NULL_STRING ,  ,  , 3 ,  , .F. , .F. )	
// but the DbCopyToArray() signature is:
//    FUNCTION DbCopyToArray(aFieldList, cbForCondition, cbWhileCondition, nNext,nRecord, lRest, lNoOptimize) AS ARRAY CLIPPER
// 
// This parameter order gives the expected result.    
//    aResult1 := DbCopyToArray( { "LAST" },  ,  , 3 )  // <-------------

// ---------------------------

	ShowArray ( aResult1 )  	
	
// ------------------	

	DbCloseArea() 
	   
	RETURN   

	
// ---------------------------
// required X# runtime sources
// --------------------------- 

INTERNAL FUNCTION DbCopyToArraySingleRecord(aFields AS IList<STRING> ) AS ARRAY // unchanged
    LOCAL result AS ARRAY 
    result := ArrayNew(aFields:Count)
    FOR VAR i := 1 TO aFields:Count
        result[i] := __FieldGet(aFields[i-1])
    NEXT
    RETURN result

FUNCTION DbCopyToArray(aFieldList, cbForCondition, cbWhileCondition, nNext,nRecord, lRest, lNoOptimize) AS ARRAY CLIPPER // unchanged
    VAR aFields := __BuildFieldList(aFieldList, FALSE)
    LOCAL aResult := {} AS ARRAY
    DbEval( {|| AAdd(aResult, DbCopyToArraySingleRecord(aFields)) }, cbForCondition, cbWhileCondition, nNext,nRecord, lRest, lNoOptimize )
    RETURN aResult 
    
INTERNAL FUNCTION __BuildFieldList(aFieldList AS USUAL, lIncludeMemo AS LOGIC) AS IList<STRING>  // modified !
VAR selected := List<STRING>{}
 
// The current "ALen(aFieldList)>0" causes an InvalidCastException because XSharp.VFP.Functions.ALen() is used
// instead of XSharp.Rt.Functions.ALen()
// 
// To make it work i replaced the line:
// IF IsArray(aFieldList) .and. ALen(aFieldList) > 0 
   
// with this one:
   IF IsArray(aFieldList) .and. XSharp.RT.Functions.ALen(aFieldList) > 0
 	
    FOREACH cFld AS STRING IN aFieldList
        selected:Add(cFld:ToString())
    NEXT
	RETURN selected
ENDIF
    LOCAL fCount AS DWORD
    fCount := FCount()
    FOR VAR nFld := 1u TO fCount
        LOCAL lInclude AS LOGIC
        LOCAL cType := NIL AS USUAL
        VoDb.FieldInfo(DBS_TYPE, nFld,@cType)
        SWITCH (STRING) cType
            CASE "M"
                lInclude := lIncludeMemo
            CASE "G"
                lInclude := FALSE
            OTHERWISE
                lInclude := TRUE
        END SWITCH
        IF lInclude
            LOCAL oVar := NULL AS OBJECT
            VoDb.FieldInfo( DBS_STRUCT, nFld, REF oVar)
            VAR oFld := (RddFieldInfo) oVar
            IF oFld:Alias != NULL
                selected:Add(oFld:Alias:ToUpperInvariant())
            ELSE
                selected:Add(oFld:Name:ToUpperInvariant())
            ENDIF
        ENDIF
    NEXT
RETURN selected    
    


Karl1155 avatar Dec 02 '21 13:12 Karl1155