HMGSCRIPT 2012: Programming For The Web in The Right Way :)

Moderator: Rathinagiri

User avatar
Rathinagiri
Posts: 5481
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Contact:

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Rathinagiri »

Roberto Lopez wrote:
apais wrote:since clipper days [ and ] are also string delimiters IE: Querytest([string])
It Works!

I've use Clipper since Autumn'86 and I've don't knew that :)

Thanks!
Wow! That's great!
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.
User avatar
Roberto Lopez
HMG Founder
Posts: 4023
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Roberto Lopez »

HMGSCRIPT R012

Now, Query() server function is generic (requires a lot of work yet).
QUERY: (Server Function)

Executes a query on the server and returns a row-selectable table with the results.

Syntax:

Query( cTable , aColumns , aHeaders )
Enjoy!
Attachments
hmgs012.zip
(626.65 KiB) Downloaded 350 times
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
User avatar
Rathinagiri
Posts: 5481
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Contact:

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Rathinagiri »

Hi Roberto,

I find this grid implementation is good enough. I am sure you might also have seen this.

https://github.com/mleibman/SlickGrid/wiki
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.
User avatar
Roberto Lopez
HMG Founder
Posts: 4023
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Roberto Lopez »

rathinagiri wrote:Hi Roberto,

I find this grid implementation is good enough. I am sure you might also have seen this.

https://github.com/mleibman/SlickGrid/wiki
As a first goal, my idea is to give to the hmgscript library, the basic functionality required to write complete applications.

A lot of things can be added as contribs, since, we are coding on top of the same document, using the same interfaces, so, the native grid, could share the same application with an add-on jquery grid.

This is the beauty of this.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
User avatar
Roberto Lopez
HMG Founder
Posts: 4023
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Roberto Lopez »

I need to create a temporary index for query function.

How to get a temporary file name in Harbour?

TIA.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
User avatar
Roberto Lopez
HMG Founder
Posts: 4023
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Roberto Lopez »

I'll stop coding the library, to dedicate to learn more about websocket protocol to solve pending server problems.

1. Safari not working.

2. Server is unable to receive messages longer than 124 characters from the client browser, it could be problematic for generic server functions like I'm planning, since a lot of parameter data are required.

If someone has info or solutions on these regards, they will be greatly welcome.

TIA.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
User avatar
Rathinagiri
Posts: 5481
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Contact:

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Rathinagiri »

Roberto Lopez wrote:I'll stop coding the library, to dedicate to learn more about websocket protocol to solve pending server problems.

1. Safari not working.

2. Server is unable to receive messages longer than 124 characters from the client browser, it could be problematic for generic server functions like I'm planning, since a lot of parameter data are required.

If someone has info or solutions on these regards, they will be greatly welcome.

TIA.
As regards to the first problem, please ignore it. We can't support all the browsers as such.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.
User avatar
bpd2000
Posts: 1207
Joined: Sat Sep 10, 2011 4:07 am
Location: India

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by bpd2000 »

Rathinagiri says correct

"As regards to the first problem, please ignore it. We can't support all the browsers as such."

First goal is HMFSCRIPT only
BPD
Convert Dream into Reality through HMG
User avatar
Roberto Lopez
HMG Founder
Posts: 4023
Joined: Wed Jul 30, 2008 6:43 pm

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Roberto Lopez »

rathinagiri wrote:
Roberto Lopez wrote:I'll stop coding the library, to dedicate to learn more about websocket protocol to solve pending server problems.

1. Safari not working.
<...>
As regards to the first problem, please ignore it. We can't support all the browsers as such.
I need that my client applications work in iPhones and iPads too, so, sadly, I can't ignore Safari.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)
Rossine
Posts: 87
Joined: Thu Jun 30, 2011 10:04 pm

Re: HMGSCRIPT 2012: Programming For The Web in The Right Way

Post by Rossine »

Hi Roberto,
Roberto Lopez wrote:I need to create a temporary index for query function.

How to get a temporary file name in Harbour?

TIA.
Below I leave a class I made for handling temporary files.

SAMPLE.PRG

Code: Select all

* Para Compilar: hbmk2 sample -lxhb

#include "dbinfo.ch"

#xcommand DEFAULT <uVar1> := <uVal1> ;
               [, <uVarN> := <uValN> ] => ;
                  If( <uVar1> == nil, <uVar1> := <uVal1>, ) ;;
                [ If( <uVarN> == nil, <uVarN> := <uValN>, ); ]

#translate CRLF => HB_OsNewLine()

request DBFCDX

*************
function MAIN
*************

cls

aStruct := { }

AAdd( aStruct, { "cod_plano", "c",  7, 0 } )
AAdd( aStruct, { "nome"     , "c", 20, 0 } )
AAdd( aStruct, { "diavenc"  , "D",  8, 0 } )
AAdd( aStruct, { "valor"    , "n", 12, 2 } )
AAdd( aStruct, { "sel_ok"   , "l",  1, 0 } )

oData1 := TDBFMEM():new()

oData1:cNome   := "TESTE1"
oData1:cAlias  := "TST1"
oData1:aStruct := aStruct
oData1:aIndex  := { { "cod_plano", "" }, ;
                    { "nome + cod_plano", "val(cod_plano) >= 1 .and. val(cod_plano) <= 10" } } 

if !oData1:create()
   quit
endif

oData1:open()

? "Vou arquivo o arquivo " + oData1:cAlias
? "Area do arquivo " + oData1:cAlias, oData1:nArea() //  o mesmo que: select( oData1:cAlias )

oData2 := TDBFMEM():new()

oData2:cNome   := "TESTE2"
oData2:cAlias  := "TST2"
oData2:aStruct := aStruct
oData2:aIndex  := { { "cod_plano", "" }, ;
                    { "nome + cod_plano", "val(cod_plano) >= 1 .and. val(cod_plano) <= 10" } } 

if !oData2:create()
   quit
endif

oData2:open()

? "Vou arquivo o arquivo " + oData2:cAlias
? "Area do arquivo " + oData2:cAlias, oData2:nArea() //  o mesmo que: select( oData1:cAlias )

msginfo( "Tecle ENTER..." )

cls

? "Arquivos carregados na memoria"

msginfo( sl_tostring( ALIAS_TEMP() ) )

cls

? "Estrutura do arquivo " + oData2:cAlias

msginfo( sl_tostring( (oData2:cAlias)->( dbstruct() ) ) )

cls

? "Informacoes do arquivo ", oData1:cAlias
? "used() ", hb_valtostr( (oData1:cAlias)->( used() ) )
? "select() ", alltrim(hb_valtostr( select( oData1:cAlias ) ))

msginfo( "Tecle ENTER..." )

cls

? "Fechei o arquivo ", oData1:cAlias

oData1:close() // Pode-se fazer assim tambem: (oData1:cAlias)->( DBCLOSEAREA() )

? "Informacoes do arquivo ", oData1:cAlias
? "used() ", hb_valtostr( (oData1:cAlias)->( used() ) )
? "select() ", alltrim(hb_valtostr( select( oData1:cAlias ) ))

msginfo( "Tecle ENTER..." )

cls

oData1:open()

? "Abri novamente o arquivo ", oData1:cAlias
? "used() ", hb_valtostr( (oData1:cAlias)->( used() ) )
? "select() ", alltrim(hb_valtostr( select( oData1:cAlias ) ))

msginfo( "Tecle ENTER..." )

cls

for n = 1 to 100
    (oData1:cAlias)->( dbappend() )
    (oData1:cAlias)->COD_PLANO := strzero( n, 7 )
    (oData1:cAlias)->NOME      := chr( 75 - n ) +"TESTE" + alltrim(str( n, 7 ))
    (oData1:cAlias)->DIAVENC   := date() + n
    (oData1:cAlias)->VALOR     := n * 1.23
    (oData1:cAlias)->SEL_OK    := iif( n % 2 = 0, .T., .F. )
next

for n = 1 to 100
    (oData2:cAlias)->( dbappend() )
    (oData2:cAlias)->COD_PLANO := strzero( n, 7 )
    (oData2:cAlias)->NOME      := chr( 75 - n ) +"TESTE" + alltrim(str( n, 7 ))
    (oData2:cAlias)->DIAVENC   := date() + n
    (oData2:cAlias)->VALOR     := n * 1.23
    (oData2:cAlias)->SEL_OK    := iif( n % 2 = 0, .T., .F. )
next

? "Posicionando no registro 2 do arquivo " + oData1:cAlias

(oData1:cAlias)->( dbgoto(2) )

? "Registro atual do arquivo " + oData1:cAlias, (oData1:cAlias)->( recno() )

? "Index atual",   "[" + (oData1:cAlias)->( DBORDERINFO( DBOI_INDEXNAME, "_" + oData1:cNome, 1 ) ) + "]"
? "Condicao do index atual", "[" + (oData1:cAlias)->( DBORDERINFO( DBOI_CONDITION, "_" + oData1:cNome, 2 ) ) + "]"

msginfo( "Tecle ENTER..." )

cls

? "Agora vou ler um registro do arquivo " + oData1:cAlias + " ordenado por " + oData1:aIndex[1,1]

(oData1:cAlias)->(DBSETORDER(1))

(oData1:cAlias)->(DBGOTOP())
if (oData1:cAlias)->( DBSEEK( "0000004", .F. ) )
   ? "0000004 EXISTE"
ELSE
   ? "0000004 NAO EXISTE"
ENDIF

? "Agora vou ler um outro registro do arquivo " + oData1:cAlias + " ordenado por " + oData1:aIndex[1,1]

(oData1:cAlias)->(DBGOTOP())
if (oData1:cAlias)->( DBSEEK( "0000112", .F. ) )
   ? "0000112 EXISTE"
ELSE
   ? "0000112 NAO EXISTE"
ENDIF

msginfo( "Tecle ENTER..." )

cls

msginfo( "Agora vou mostrar o browse do arquivo " + oData1:cAlias + " ordenado por " + oData1:aIndex[1,1] )

cls

(oData1:cAlias)->(DBGOTOP())
(oData1:cAlias)->( browse() )

cls

msginfo( "Agora vou mostrar o browse do arquivo " + oData1:cAlias + " ordenado por " + oData1:aIndex[2,1] )

cls

(oData1:cAlias)->(DBSETORDER(2))
(oData1:cAlias)->(DBGOTOP())
(oData1:cAlias)->( browse() )

msginfo( "Agora vou mostrar o browse do arquivo " + oData2:cAlias + " ordenado por " + oData1:aIndex[1,1] )

(oData2:cAlias)->(DBSETORDER(1))
(oData2:cAlias)->(DBGOTOP())
(oData2:cAlias)->( browse() )

cls

oData1:close()

? "Fechei <TESTE1>"
? "Quais alias estao na memoria ?"

msginfo( sl_tostring( ALIAS_TEMP() ) )

cls

msginfo( "Vou reabrir <TESTE1>" )

oData1:Open()

cls

? "Quais alias estao na memoria ?"

msginfo( sl_tostring( ALIAS_TEMP() ) )

msginfo( "Agora vou mostrar o browse do arquivo " + oData1:cAlias + " ordenado por " + (oData1:cAlias)->(indexkey()) )

(oData1:cAlias)->(DBGOTOP())
(oData1:cAlias)->( browse() )

cls

? "Fechando o arquivo " + oData1:cAlias

oData1:close()
oData1:destroy()

oData1 := NIL

msginfo( "Fechando o arquivo " + oData2:cAlias )

oData2:close()
oData2:destroy()

oData2 := NIL

cls

? "Quais alias estao na memoria ?"

msginfo( sl_tostring( ALIAS_TEMP() ) )

cls

? ""
? ""
? "bye..."
? ""
? ""
? ""

return NIL

********************
function SL_ToString( x, lLineFeed, lInherited, lType, cFile, lForceLineFeed )
********************

    local s := ''
    local t := valtype( x )
    local i, j

    DEFAULT lLineFeed      := .T.
    DEFAULT lInherited     := .F.
    DEFAULT lType          := .F.
    DEFAULT cFile          := ""
    DEFAULT lForceLineFeed := .F.
    
    do case
       case ( t == "C" )
            s := iif( lType, "[C]=", "" ) + '"' + x + '"'
       case ( t == "N" )
            s := iif( lType, "[N]=", "" ) + alltrim(str( x ))
       case ( t == "D" )
            s := iif( lType, "[D]=", "" ) + "ctod('"+ dtoc(x) +"')"
       case ( t == "L" )
            s := iif( lType, "[L]=", "" ) + iif( x, '.T.', '.F.' )
       case ( t == "M" )
            s := iif( lType, "[M]=", "" ) + '"' + x + '"'
       case ( t == "B" )
            s := iif( lType, "[B]=", "" ) + '{|| ... }'
       case ( t == "U" )
            s := iif( lType, "[U]=", "" ) + 'NIL'
       case ( t == "A" )
            s := iif( lType, "[A]=", "" ) + "{"
            if len(x) = 0
               s += " "
            else
               s += iif( valtype( x[1] ) = "A" .or. lForceLineFeed, CRLF, "" )
               j := len(x)
               
               for i := 1 to j
                   s += iif( valtype( x[i] ) == "A", "  ", " " ) + iif( lForceLineFeed, " ", "" ) + SL_ToString( x[i], .F. )
                   s += iif( i <> j, ",", "" )
                   if lLineFeed
                      if !lInherited .and. ( valtype( x[i] ) == "A" .or. lForceLineFeed )
                         s += CRLF
                      endif
                   endif
               next
            endif         
            s += iif( !lForceLineFeed, " ", "" ) + "}"

       case ( t == "O" )
            if lInherited
               && É necessário linkar \harbour\lib\xhb.lib
               s := iif( lType, "[O]=", "" ) + hb_dumpvar( x ) + iif( lLineFeed, CRLF, "" )
            else
               s := iif( lType, "[O]=", "" ) + x:ClassName()+'():New()' + iif( lLineFeed, CRLF, "" )
            endif
    endcase
    
    if !empty( cFile )
       memowrit( cFile, s )
    endif
    
return s

****************
function msginfo( cMsg )
****************

wait cMsg

return NIL

#include "tdbfmem.prg"


TDBFMEM.PRG

Code: Select all


#include "dbinfo.ch"
#include "hbclass.ch"

//----------------------------------------------------------------------------//
static aAliases
//----------------------------------------------------------------------------//

CLASS TDBFMEM

    DATA cNome     INIT ""
    DATA cNomeTemp INIT ""
    DATA cAlias    INIT ""
    DATA cModo     INIT "E"   // E=Exclusive / S=Shared
    DATA aStruct   INIT { }
    DATA aIndex    INIT { }
    
    METHOD Create()
    METHOD Open()
    METHOD Close()
    METHOD Destroy()
    METHOD nArea() INLINE select( ::cAlias )

    METHOD New() CONSTRUCTOR

ENDCLASS

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

METHOD New() CLASS TDBFMEM

   local cDirTemp

   if valtype( aAliases ) = "U"
      aAliases := { => } // hb_hash()
   endif

   cDirTemp := GetEnv( "TEMP" )
   if empty( cDirTemp ) ; cDirTemp := GetEnv( "TMP" ) ; endif
   if empty( cDirTemp ) ; cDirTemp := "."             ; endif

   ::cNomeTemp := cDirTemp + "\MEM:"

return SELF

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

METHOD Create() CLASS TDBFMEM

   local n, cData, cCond, aAlias

   ::cAlias := upper(::cAlias)
   ::cNome  := upper(::cNome)

   aAlias   := ALIAS_TEMP()

   if ascan( aAlias, { |aElem| aElem[1] == ("MEM:" + ::cNome) } ) > 0
      MsgInfo( "Nome de arquivo [" + ::cNome + "] já Existe na memória !!!" + CRLF + ;
               "O sistema será abandonado !!!", "..:: Atenção ::.." )
      return .F.
   endif   

   if hb_HHasKey( aAliases, ::cAlias )
      MsgInfo( "Alias [" + ::cAlias + "] já Existe na memória !!!" + CRLF + ;
               "O sistema será abandonado !!!", "..:: Atenção ::.." )
      return .F.
   else
      aAliases[::cAlias] := "MEM:" + ::cNome
   endif   

   DbCreate( (::cNomeTemp + ::cNome), ::aStruct, "DBFCDX", .T., (::cAlias) )

   ::close()

//   ::Open()

return .T.

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

METHOD Open() CLASS TDBFMEM

   aAliases[::cAlias] := "MEM:" + ::cNome
   
   if ::cModo = "E"
      Use ( ::cNomeTemp + ::cNome ) Alias (::cAlias) via "DBFCDX" New Exclusive
   else                                                                   
      Use ( ::cNomeTemp + ::cNome ) Alias (::cAlias) via "DBFCDX" New shared   
   endif

   if !empty( ::aIndex )
      for n = 1 to len(::aIndex)
          cData := ::aIndex[n,1]
          cCond := ::aIndex[n,2]
          if empty( cCond  )
             (::cAlias)->( ordCondSet(      ,,,,         ,, recno(),,,,,, iif( n = 1, .F., .T. ),,,,, .T.,, ) )
          else
             (::cAlias)->( ordCondSet( cCond,,,, &(cCond),, recno(),,,,,, iif( n = 1, .F., .T. ),,,,, .T.,, ) )
          endif
          (::cAlias)->( ordCreate( "_" + ::cNome, "I" + strzero( n, 2 ), cData, &(cData), ) )
      next
   endif

return ::nArea

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

METHOD close() CLASS TDBFMEM

   local n

   if ( n := hb_hPos( aAliases, ::cAlias ) ) > 0
      hb_hDelAt( aAliases, n )
   endif

   (::cAlias)->( dbclosearea() )

return NIL

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

METHOD destroy() CLASS TDBFMEM

   if empty( aAliases )
      aAliases := NIL
   endif

   hb_dbdrop( ::cNomeTemp + ::cNome )

   hb_GCALL( .T. )

return NIL // ( ferase( "mem" ) = 0 )

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

*******************
function ALIAS_TEMP
*******************

local aAlias := { }, cKey
local aKeys

if valtype( aAliases ) = "U"
   return aAlias
endif
   
aKeys := hb_HKeys( aAliases )

for each cKey IN aKeys
    aadd( aAlias, { hb_HGet( aAliases, cKey ), cKey } )
next      

return aAlias

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

// EOF //

I hope that will help you :D

Best Regards,

Rossine.
Post Reply