Files
harbour-core/harbour/contrib/hbpgsql/tests/cache.prg
Viktor Szakats b1bfe8f54b 2012-11-29 00:49 UTC+0100 Viktor Szakats (harbour syenar.net)
* contrib/hbwin/hbole.ch
    ! missing svn props

  * contrib/hbwin/hbsim.ch
  * contrib/hbfoxpro/hbfoxpro.ch
  * contrib/hbmysql/mysql.ch
    ! added missing self-guards
      This was a requirement, but now it really must
      be done, if a header wants to be put in headers=
      directive in a .hbc file for auto-inclusion.

  * contrib/hbmysql/tests/dbf2mysq.prg
    ! missing #require directive

  * contrib/hbblat/hbblat.hbc
  * contrib/hbblink/hbblink.hbc
  * contrib/hbbz2/hbbz2.hbc
  * contrib/hbcairo/hbcairo.hbc
  * contrib/hbcurl/hbcurl.hbc
  * contrib/hbexpat/hbexpat.hbc
  * contrib/hbfimage/hbfimage.hbc
  * contrib/hbfoxpro/hbfoxpro.hbc
  * contrib/hbgd/hbgd.hbc
  * contrib/hbhpdf/hbhpdf.hbc
  * contrib/hblzf/hblzf.hbc
  * contrib/hbmagic/hbmagic.hbc
  * contrib/hbmlzo/hbmlzo.hbc
  * contrib/hbmxml/hbmxml.hbc
  * contrib/hbmysql/hbmysql.hbc
  * contrib/hbmzip/hbmzip.hbc
  * contrib/hbnetio/hbnetio.hbc
  * contrib/hbpgsql/hbpgsql.hbc
  * contrib/hbsqlit3/hbsqlit3.hbc
  * contrib/hbssl/hbssl.hbc
  * contrib/hbtpathy/hbtpathy.hbc
  * contrib/hbxdiff/hbxdiff.hbc
  * contrib/hbzebra/hbzebra.hbc
  * contrib/rddsql/rddsql.hbc
    + added .ch headers to .hbc files for
      autoload.
    ; For some contribs it still has to do
      for several reasons, f.e. .ch file overrides
      standard features so they must stay optional,
      or they must be optional for other reasons,
      or they have multiple headers and I didn't
      decide yet which one of those should be
      standard.

  * contrib/hbexpat/tests/test.prg
  * contrib/hbexpat/tests/tohash.prg
  * contrib/hbfimage/tests/fitest.prg
  * contrib/hbgd/tests/animgif.prg
  * contrib/hbgd/tests/antialia.prg
  * contrib/hbgd/tests/counter.prg
  * contrib/hbgd/tests/gdtest.prg
  * contrib/hbgd/tests/gdtestcl.prg
  * contrib/hbgd/tests/test_out.prg
  * contrib/hbgd/tests/testdpi.prg
  * contrib/hbgd/tests/tostring.prg
  * contrib/hbgd/tests/tpoly.prg
  * contrib/hbhpdf/tests/harupdf.prg
  * contrib/hblzf/tests/test.prg
  * contrib/hbmlzo/tests/test.prg
  * contrib/hbpgsql/tests/cache.prg
  * contrib/hbpgsql/tests/stress.prg
  * contrib/hbpgsql/tests/test.prg
  * contrib/hbsqlit3/tests/authoriz.prg
  * contrib/hbsqlit3/tests/backup.prg
  * contrib/hbsqlit3/tests/blob.prg
  * contrib/hbsqlit3/tests/hooks.prg
  * contrib/hbsqlit3/tests/metadata.prg
  * contrib/hbsqlit3/tests/pack.prg
  * contrib/hbsqlit3/tests/sl3_test.prg
  * contrib/hbssl/tests/bio.prg
  * contrib/hbssl/tests/crypt.prg
  * contrib/hbssl/tests/digest.prg
  * contrib/hbssl/tests/encode.prg
  * contrib/hbssl/tests/pem.prg
  * contrib/hbssl/tests/test.prg
  * contrib/hbxdiff/tests/test.prg
  * contrib/hbxdiff/tests/test2.prg
  * contrib/hbxdiff/tests/test3.prg
  * contrib/hbzebra/tests/testcair.prg
  * contrib/hbzebra/tests/testhpdf.prg
  * contrib/hbzebra/tests/testwin.prg
  * contrib/sddmy/tests/test1.prg
  * contrib/sddoci/tests/test1.prg
  * contrib/sddodbc/tests/test1.prg
  * contrib/sddodbc/tests/test2.prg
  * contrib/sddsqlt3/tests/test1.prg
    % no longer use #include to include standard
      package headers. Rely on autoload triggered
      by .hbc file or #require directive.
2012-11-29 00:04:11 +00:00

580 lines
12 KiB
Plaintext

/*
* $Id$
*/
/*
* This samples show how to use dbf to cache postgres records.
*/
#require "hbpgsql"
#define DB_ALIAS 1
#define DB_FILE 2
#define DB_QUERY 3
#define DB_ROW 4
#define DB_FETCH 5
STATIC s_oServer
STATIC s_aTableTemp := {}
STATIC s_aTempDBF := {}
PROCEDURE Main( cServer, cDatabase, cUser, cPass )
LOCAL i
LOCAL cQuery
IF SQLConnect( cServer, cDatabase, cUser, cPass )
QuickQuery( "DROP TABLE test" )
cQuery := "CREATE TABLE test ( "
cQuery += " codigo integer primary key, "
cQuery += " descri char(50), "
cQuery += " email varchar(50) ) "
SQLQuery( cQuery )
SQLOpen( "nomes", "SELECT * FROM test" )
FOR i := 1 TO 50
APPEND BLANK
REPLACE codigo WITH i
REPLACE descri WITH "test " + Str( i )
NEXT
SQLApplyUpdates()
cQuery := "SELECT * FROM test WHERE codigo >= :1 ORDER BY codigo"
cQuery := SQLPrepare( cQuery, 1 )
SQLOpen( "nomes", cQuery )
DO WHILE ! Eof()
? RecNo(), nomes->Codigo, nomes->descri, nomes->email
IF RecNo() == 10
DELETE
ENDIF
IF RecNo() == 20
REPLACE email WITH "teste"
ENDIF
SQLFetch()
ENDDO
SQLApplyUpdates()
ENDIF
SQLGarbageCollector()
RETURN
/* Put theses functions in a library */
FUNCTION SQLApplyUpdates()
LOCAL cAlias := Upper( Alias() )
LOCAL i, x
LOCAL oQuery
LOCAL oRow
LOCAL lUpdate
LOCAL lError := .F.
LOCAL cError
i := AScan( s_aTableTemp, {| aVal | aVal[ DB_ALIAS ] == cAlias } )
IF i != 0
oQuery := s_aTableTemp[ i ][ 3 ]
FOR i := 1 TO LastRec()
dbGoto( i )
IF i > oQuery:LastRec()
/* Verifica se eh um registro novo */
IF ! Deleted()
oRow := oQuery:GetBlankRow()
FOR x := 1 TO FCount()
IF oRow:FieldPos( FieldName( x ) ) != 0
oRow:FieldPut( FieldName( x ), FieldGet( x ) )
ENDIF
NEXT
oQuery:Append( oRow )
cError := oQuery:ErrorMsg()
lError := oQuery:NetErr()
ENDIF
ELSE
oRow := oQuery:GetRow( i )
lUpdate := .F.
IF Deleted()
oQuery:Delete( oRow )
cError := oQuery:ErrorMsg()
lError := oQuery:NetErr()
ELSE
/* Faz update, mas compara quais campos sao diferentes */
FOR x := 1 TO FCount()
IF oRow:FieldPos( FieldName( x ) ) != 0
IF ! ( FieldGet( x ) == oRow:FieldGet( FieldName( x ) ) )
oRow:FieldPut( FieldName( x ), FieldGet( x ) )
lUpdate := .T.
ENDIF
ENDIF
NEXT
IF lUpdate
oQuery:Update( oRow )
cError := oQuery:ErrorMsg()
lError := oQuery:NetErr()
ENDIF
ENDIF
ENDIF
IF lError
EXIT
ENDIF
NEXT
ENDIF
IF lError
Alert( cError )
ENDIF
RETURN ! lError
PROCEDURE SQLCloseTemp( cAlias )
LOCAL x
IF ! Empty( Select( cAlias ) )
( cAlias )->( dbCloseArea() )
ENDIF
x := AScan( s_aTableTemp, {| aVal | aVal[ DB_ALIAS ] == cAlias } )
IF ! Empty( x )
ADel( s_aTableTemp, x )
// ASize( s_aTableTemp, Len( s_aTableTemp ) - 1 )
ENDIF
RETURN
PROCEDURE SQLGarbageCollector()
LOCAL i
LOCAL oQuery
dbCloseAll()
FOR i := 1 TO Len( s_aTableTemp )
/* Apaga arquivos dbfs criados */
FErase( s_aTableTemp[ i ][ DB_FILE ] )
oQuery := s_aTableTemp[ i ][ DB_QUERY ]
IF oQuery != NIL
oQuery:Destroy()
ENDIF
NEXT
FOR i := 1 TO Len( s_aTempDBF )
IF hb_FileExists( s_aTempDBF[ i ] )
FErase( s_aTempDBF[ i ] )
ENDIF
IF hb_FileExists( StrTran( s_aTempDBF[ i ], ".tmp", ".dbf" ) )
FErase( StrTran( s_aTempDBF[ i ], ".tmp", ".dbf" ) )
ENDIF
IF hb_FileExists( StrTran( s_aTempDBF[ i ], ".tmp", ".dbt" ) )
FErase( StrTran( s_aTempDBF[ i ], ".tmp", ".dbt" ) )
ENDIF
NEXT
s_aTableTemp := {}
s_aTempDBF := {}
RETURN
FUNCTION SQLFetch( fetchall )
LOCAL oQuery
LOCAL oRow
LOCAL cAlias := Upper( Alias() )
LOCAL i, x, y
LOCAL nPos
LOCAL lEof := .F.
hb_default( @Fetchall, .F. )
/* Procura pela tabela no array */
i := AScan( s_aTableTemp, {| aVal | aVal[ DB_ALIAS ] == cAlias } )
IF i != 0
/* Traz registros da base de dados */
oQuery := s_aTableTemp[ i ][ DB_QUERY ]
nPos := s_aTableTemp[ i ][ DB_ROW ] + 1
IF Fetchall
s_aTableTemp[ i ][ DB_FETCH ] := .T.
ENDIF
IF oQuery:LastRec() >= nPos
y := nPos
DO WHILE nPos <= iif( FetchAll, oQuery:LastRec(), y )
oRow := oQuery:GetRow( nPos )
dbAppend()
FOR x := 1 TO oRow:FCount()
FieldPut( FieldPos( oRow:FieldName( x ) ), oRow:FieldGet( x ) )
NEXT
s_aTableTemp[ i ][ DB_ROW ] := nPos
nPos++
ENDDO
ELSE
// Posiciona registro no eof
dbSkip()
ENDIF
lEof := nPos > oQuery:LastRec()
ENDIF
RETURN lEof
PROCEDURE SQLFetchAll()
SQLFetch( .T. )
dbGoTop()
RETURN
FUNCTION SQLOpen( cAlias, cQuery, xFetch, cOrder )
LOCAL cFile
LOCAL Result := .T.
LOCAL x
LOCAL s_oServer
LOCAL oQuery
LOCAL aStrudbf
LOCAL lFetch
s_oServer := SQLCurrentServer()
cAlias := Upper( cAlias )
/* Procura por query na area temporaria */
x := AScan( s_aTableTemp, {| aVal | aVal[ DB_ALIAS ] == cAlias } )
IF ! Empty( x )
oQuery := s_aTableTemp[ x ][ 3 ]
oQuery:Destroy()
ENDIF
IF cQuery == NIL
cQuery := "SELECT * FROM " + cAlias
IF ! Empty( cOrder )
cQuery += " ORDER BY " + cOrder
ENDIF
ENDIF
cQuery := cQuery
oQuery := s_oServer:Query( cQuery )
IF oQuery:NetErr()
Alert( oQuery:ErrorMsg() )
RETURN .F.
ENDIF
IF Empty( Select( cAlias ) )
/* Pega estrutura da base de dados */
aStrudbf := oQuery:Struct()
/* Cria tabela */
cFile := TempFile()
dbCreate( cFile, aStrudbf )
/* Abre Tabela */
dbUseArea( .T., NIL, cFile, cAlias, .F. )
ELSE
Select( cAlias )
ZAP
ENDIF
IF xFetch != NIL
lFetch := xFetch
ELSE
lFetch := .F.
ENDIF
/* Se nao houver query na area temporaria entao adiciona, caso contrario, apenas atualiza */
IF Empty( x )
AAdd( s_aTableTemp, { ;
cAlias, ; // Table Name
cFile, ; // Temporary File Name
oQuery, ; // Object Query
0, ; // Current Row
lFetch } ) // Fetch Status
ELSE
s_aTableTemp[ x ][ DB_QUERY ] := oQuery
s_aTableTemp[ x ][ DB_ROW ] := 0
s_aTableTemp[ x ][ DB_FETCH ] := lFetch
ENDIF
/* Traz registros da base de dados */
SQLFetch( lFetch )
IF lFetch
dbGoTop()
ENDIF
RETURN result
FUNCTION SQLConnect( cServer, cDatabase, cUser, cPassword, cSchema )
LOCAL lRetval := .T.
s_oServer := TPQServer():New( cServer, cDatabase, cUser, cPassWord, 5432, cSchema )
IF s_oServer:NetErr()
Alert( s_oServer:ErrorMsg() )
lRetval := .F.
ENDIF
s_oServer:lAllCols := .F.
RETURN lRetval
PROCEDURE SQLDestroy()
IF s_oServer != NIL
s_oServer:Destroy()
ENDIF
RETURN
FUNCTION SQLCurrentServer
RETURN s_oServer
FUNCTION SQLQuery( cQuery )
LOCAL oQuery := s_oServer:Query( cQuery )
IF oQuery:NetErr()
Alert( cQuery + ":" + oQuery:ErrorMsg() )
ENDIF
RETURN oQuery
FUNCTION SQLExecQuery( cQuery )
LOCAL oQuery
LOCAL result := .T.
oQuery := s_oServer:Query( cQuery )
IF oQuery:NetErr()
Alert( "Cannot execute " + cQuery + ":" + oQuery:ErrorMsg() )
result := .F.
ELSE
oQuery:Destroy()
ENDIF
RETURN result
FUNCTION SQLPrepare( cQuery, ... )
LOCAL i, x
IF PCount() >= 2
/* Limpa espacos desnecessarios */
DO WHILE At( Space( 2 ), cQuery ) != 0
cQuery := StrTran( cQuery, Space( 2 ), Space( 1 ) )
ENDDO
/* Coloca {} nos parametros */
FOR i := 1 TO PCount() - 1
IF ! Empty( x := At( ":" + hb_ntos( i ), cQuery ) )
cQuery := Stuff( cQuery, x, 0, "{" )
cQuery := Stuff( cQuery, x + Len( hb_ntos( i ) ) + 2, 0, "}" )
ENDIF
NEXT
/* Substitui parametros por valores passados */
FOR i := 2 TO PCount()
x := hb_PValue( i )
IF x != NIL .AND. Empty( x )
x := "null"
ELSEIF HB_ISNUMERIC( x )
x := hb_ntos( x )
ELSEIF HB_ISDATE( x )
x := DToQ( x )
ELSEIF HB_ISLOGICAL( x )
x := iif( x, "'t'", "'f'" )
ELSEIF HB_ISSTRING( x )
x := SToQ( RTrim( x ) )
ELSE
x := "null"
ENDIF
cQuery := StrTran( cQuery, "{:" + hb_ntos( i - 1 ) + "}", x )
NEXT
ENDIF
cQuery := StrTran( cQuery, "==", "=" )
cQuery := StrTran( cQuery, "!=", "<>" )
cQuery := StrTran( cQuery, ".and.", "and" )
cQuery := StrTran( cQuery, ".or.", "or" )
cQuery := StrTran( cQuery, ".not.", "not" )
RETURN cQuery
/* Pega resultado de uma sequence */
FUNCTION SQLSequence( Sequence_name )
RETURN Val( QuickQuery( "SELECT nextval(" + SToQ( sequence_name ) + ")" ) )
PROCEDURE SQLStartTrans()
IF PQtransactionStatus( s_oServer:pDB ) != PQTRANS_INTRANS
s_oServer:StartTransaction()
ENDIF
RETURN
FUNCTION SQLInTrans()
RETURN PQtransactionStatus( s_oServer:pDB ) == PQTRANS_INTRANS
PROCEDURE SQLCommitTrans()
s_oServer:Commit()
RETURN
PROCEDURE SQLRollbackTrans()
s_oServer:rollback()
RETURN
/* Faz querie que retorna apenas 1 valor de coluna */
FUNCTION QuickQuery( cQuery )
LOCAL pQuery
LOCAL result := ""
LOCAL temp, aTemp
LOCAL x, y
pQuery := PQexec( s_oServer:pDB, cQuery )
IF PQresultStatus( pQuery ) == PGRES_TUPLES_OK
IF PQlastrec( pQuery ) != 0
IF PQfcount( pQuery ) == 1 .AND. PQlastrec( pQuery ) == 1
temp := PQgetvalue( pQuery, 1, 1 )
result := iif( temp == NIL, "", temp )
ELSE
result := {}
FOR x := 1 TO PQlastrec( pQuery )
aTemp := {}
FOR y := 1 TO PQfcount( pQuery )
temp := PQgetvalue( pQuery, x, y )
AAdd( aTemp, iif( temp == NIL, "", temp ) )
NEXT
AAdd( result, aTemp )
NEXT
ENDIF
ENDIF
ENDIF
RETURN result
PROCEDURE MakeDBF( cAlias, aStructure, aIndex )
LOCAL cFile, i, cIndex, cKey
hb_default( @aIndex, {} )
cFile := TempFile()
dbCreate( cFile, aStructure )
/* Abre Tabela */
dbUseArea( .T., NIL, cFile, cAlias, .F. )
FOR i := 1 TO Len( aIndex )
cKey := aIndex[ i ]
cIndex := TempFile()
INDEX ON &cKey TO ( cIndex )
AAdd( s_aTempDBF, cIndex )
NEXT
AAdd( s_aTempDBF, cFile )
RETURN
FUNCTION TempFile( cPath, cExt )
LOCAL cString
hb_default( @cPath, hb_DirTemp() )
hb_default( @cExt, "tmp" )
cString := cPath + StrZero( Int( hb_Random( Val( StrTran( Time(), ":" ) ) ) ), 8 ) + "." + cExt
DO WHILE hb_FileExists( cString )
cString := cPath + StrZero( Int( hb_Random( Val( StrTran( Time(), ":" ) ) ) ), 8 ) + "." + cExt
ENDDO
RETURN cString
FUNCTION DToQ( cData )
RETURN "'" + Str( Year( cData ), 4 ) + "-" + StrZero( Month( cData ), 2 ) + "-" + StrZero( Day( cData ), 2 ) + "'"
FUNCTION SToQ( cData )
RETURN "'" + cData + "'"