Página 1 de 3

Harbour + SQLMIX

Enviado: 29 Abr 2026 22:50
por MSDN_7
Montei um exemplo para acessar um banco SQL usando Harbour e SQLMIX, conecta, tudo ok, porém, não consigo gravar em uma tabela, tento usar via SQL ( insert into nome_tabela values (xx, xxx, xxx) ) e via tabela->(dbappend), nenhuma das formas funciona, alguém tem alguma sugestão ?
Obrigado

Re: Harbour + SQLMIX

Enviado: 30 Abr 2026 00:05
por alxsts
Olá!

Nunca usei SQLMIX mas, independentemente do método de acesso ao banco de dados, pode ser que haja algum problema de configuração nas permissões do usuário e/ou da tabela...

Em qualquer caso, seria interessante e ajudaria se você postasse o código usado, tanto para conectar quanto para gravar no banco, bem como informasse qual banco de dados está utilizando.

Re: Harbour + SQLMIX

Enviado: 30 Abr 2026 10:56
por MSDN_7
Bom dia,

Segue o código que não executa a gravação na tabela.

Código: Selecionar todos

          @ 09,11 say 'Descrição:' get v_descricao pict '@!'
          @ 10,11 say 'Modelo   :' get v_modelo pict '@!'
          read

          if lastkey() == 27
               deli_off()
               setcolor(cor)
               restscreen(,,,,tela)
               return( nil )
          endif

          Quadro3(11,26,13,52)
          @ 12,28 prompt ' Gravar '
          @ 12,38 prompt ' Não Gravar '
          menu to op

          do case
               case op == 1
                    cSql := "INSERT INTO produto (descricao, modelo) VALUES ('DESC_TESTE','MODELO_TESTE')"
                    if RDDInfo( RDDI_EXECUTE, cSql, , oCon ) <> NIL
                         alert('Gravou')
                    else
                         alert('Não gravou')
                    endif
                    exit
               case op == 2
                    exit
          endcase
Da forma como está, mostra a mensagem " gravou ", mas sem efetivamente estar registrado na tabela.
Pesquisei todos os exemplos que encontrei, dentro da pasta contrib do Harbour, internet, para ver se havia uma forma diferente de gravar os dados no banco, mas não achei nada diferente disso, por isso, quem souber, agradeço a ajuda.

Abraço

Re: Harbour + SQLMIX

Enviado: 30 Abr 2026 14:01
por alxsts
Olá!

Tente trocar esta linha

Código: Selecionar todos

if RDDInfo( RDDI_EXECUTE, cSql, , oCon ) <> NIL
Por

Código: Selecionar todos

if RDDInfo( RDDI_EXECUTE, cSql, "SQLMIX", oCon ) <> NIL

Re: Harbour + SQLMIX

Enviado: 30 Abr 2026 15:28
por MSDN_7
Fiz a alteração, mas continua igual, não grava no banco as informações.
Existe algum exemplo mais robusto do uso da SQLMIX, onde seja possível observar um CRUD, e aprender a forma correta de usar essa lib ?

Re: Harbour + SQLMIX

Enviado: 30 Abr 2026 16:02
por alxsts
Olá!

Como informei anteriormente, não tenho experiência com a ferramenta.

Talvez falte um COMMIT. Alguns SGBD não fazem isto automaticamente. Também não sabemos como está conectando. Consegue fazer SELECT nesta conexão?

Creio que o Itamar possa te ajudar mais. Creio que ele seja o usuário mais experiente em Sqlmix aqui no fórum. Vamos aguardar.

Re: Harbour + SQLMIX

Enviado: 30 Abr 2026 17:16
por MSDN_7
Sim, consigo conectar, consigo fazer select, abrir a tabela e navegar usando TBrowse, perfeito, mas na hora de incluir, não funciona. Estou usando o Harbour nightly ( de 3 dias atrás ), todas as lib ok.

Re: Harbour + SQLMIX

Enviado: 01 Mai 2026 22:04
por MSDN_7
Não consegui achar solução, infelizmente não funciona o SQLMIX, mais uma vez injetaram algo no Harbour feito pela metade, só perde-se tempo com algo que não funciona 100%, triste, mas verdade !

Re: Harbour + SQLMIX

Enviado: 01 Mai 2026 22:15
por Itamar M. Lins Jr.
Olá!
Sempre que usei funcionou com MySQL/MariaDB e PG.
Inclusive tem aqui os códigos.
https://pctoledo.org/viewtopic.php?t=28196

Re: Harbour + SQLMIX

Enviado: 01 Mai 2026 22:20
por Itamar M. Lins Jr.
Olá!
Com MSSQL.
Alias todas as minhas postagens é usando SQLMIX.
https://pctoledo.org/viewtopic.php?t=27536

Tem até projeto na Hwgui.

Código: Selecionar todos

itamar@itamar-I7:~/dev/hwgui-code/hwgui/samples/MariaDb$ ls -l
total 24
-rw-rw-r-- 1 itamar itamar   710 Mar 11 19:58 hbmk.hbm
-rw-rw-r-- 1 itamar itamar   106 Mar 11 19:58 hwgui_crud.hbc
-rw-rw-r-- 1 itamar itamar   123 Mar 11 19:58 hwgui_crud.hbp
-rw-rw-r-- 1 itamar itamar 10080 Mar 11 19:58 hwgui_crud.prg
itamar@itamar-I7:~/dev/hwgui-code/hwgui/samples/MariaDb$ 
Quando vc fez a pergunta lá no outro grupo sobre o ARM... Isso roda sem BO "desde priscas eras" A resposta do Przmek, mais de 20 anos pronto !
Mesma coisa aqui para o SQLMIX.

Re: Harbour + SQLMIX

Enviado: 01 Mai 2026 22:26
por Itamar M. Lins Jr.
Olá!
Segue o código do exemplo em Hwgui. Linux/Windows.
if RDDInfo( RDDI_EXECUTE, cSql, , oCon ) <> NIL
Veja que vc usa <> para comparar retorno YES/NO .T. ou .F. No seu sempre será VERDADEIRO mesmo falhando.
Como deve ser:
If rddInfo( RDDI_EXECUTE, cSQL )
Mas tá lá nos exemplos isso. Na pasta dele.

Código: Selecionar todos

#require "rddsql"
#require "sddodbc" //SQLMIX

#include "hwgui.ch"
#include "set.ch"
#include "dbinfo.ch"

REQUEST HB_CODEPAGE_UTF8EX
REQUEST DBFCDX, DBFFPT

//For MariaDB via SQLMIX
REQUEST SQLMIX, SDDODBC

MEMVAR cName, nIdContact, cPhantom
MEMVAR oName, oIdContact, oPhantom
MEMVAR lAdd

Function Test
   Local oMain


   INIT WINDOW oMain MAIN TITLE "GRUD DBF - MariaDB" AT 100, 100 SIZE 400, 300

   MENU OF oMain

      MENU TITLE "&Files"
         MENUITEM "&Contacts DBF" ACTION Contacts_DBF()
         SEPARATOR
         MENUITEM "&Contacts MariaDB" ACTION Contacts_MariaDB()
         SEPARATOR

      MENUITEM "&Exit" ACTION oMain:Close()
      ENDMENU

      MENU TITLE "&Help"
         MENUITEM "&About" ACTION hwg_Msginfo( HwG_Version(), "About" )
      ENDMENU

   ENDMENU

   ACTIVATE WINDOW oMain CENTER

Return Nil

Function Contacts_DBF
   Local oDlg, oBrw, oTab, oFontDlg, oFontBrw //Controls of Dialog
   Local oBtnDel, oBtnSave, oBtnAdd, oBtnOnOff //Controls of Dialog
   Local aStructure, lSQL := .F.

   Private nIdContact, cName, cPhantom := space(1)  //Fields of DataBase
   Private lAdd := .F.

   rddSetDefault("DBFCDX")
   Set Autopen On
   hb_cdpSelect("UTF8EX")

   aStructure := { { "idcontact" ,"+",04,0} ,; //Auto increment
                   { "name"      ,"c",60,0} }

   If !hb_vfexists("contacts.dbf")
      If dbcreate("contacts.dbf",aStructure,"DBFCDX",.t.,"ctc") //Create and open with shared mode
         index on field->name tag tgName
         ctc->( dbappend() )
         ctc->name := "JOSÉ DE ASSUMPÇÃO"
         ctc->( dbappend() )
         ctc->name := "MARIA ANTONIETA"
         ctc->( dbappend() )
         ctc->name := "SNOOPY"
         ctc->( dbappend() )
         ctc->name := "POPEYE"
         ctc->(DbDelete())

         ctc->( dbCloseArea() )
      Else
         hwg_MsgStop("Error Creating DBF")
         cancel
      EndIf
   EndIf

   PREPARE FONT oFontDlg NAME "Z003" Width 0 Height 16
   PREPARE FONT oFontBrw NAME "Courier" Width 0 Height 14

   Use contacts new shared alias "ctc"

INIT DIALOG oDlg CLIPPER NOEXIT TITLE "Contacts Via DBFCDX" AT 0,0 size 1024,500 Font oFontDlg STYLE DS_CENTER
   @ 10,080 browse oBrw DataBase Of oDlg size 360,400 Font oFontBrw ;
   On PosChange {|| UpdateGets() }

   oBrw:Alias:="ctc"

   Add Column {||iif(ctc->(Deleted()),"Yes","No" ) } to oBrw ;
   Header "Del" Length 3

   Add Column FieldBlock("idcontact") to oBrw ;
   Header "Cont_ID" Length 10

   Add Column FieldBlock("name") to oBrw ;
   Header "Name" length 100

   @ 370,005 Tab oTab Items {} size 600,430 of oDlg

      BEGIN PAGE "Contacts" of oTab

         FieldsGet()

         @ 010,010 GroupBox "ID" size 120,60
         @ 020,030 Get oIdContact var nIdContact Picture "9999999999" size 090,30 STYLE ES_RIGHT

         @ 010,080 GroupBox "Name" size 500,60
         @ 020,100 Get oName var cName size 470,30 //ToolTip "Name of contact"

         @ 020,160 Get oPhantom var cPhantom size 0,0 //Phantom get to validate last get

      END Page Of oTab

   @ 370,440 button oBtnSave   Caption "Save"   on click {||SaveContact(oDlg,lSQL)} size 90,50
   @ 470,440 button oBtnAdd    Caption "Add"    on click {||NewContact()}           size 90,50
   @ 570,440 button oBtnDel    Caption "Del"    on click {||DelContact(oDlg,lSQL)}  size 90,50
   @ 670,440 button oBtnOnOff  Caption "On Off" on click {||DelOnOff(oDlg)}         size 90,50

oDlg:Activate()

ctc->( dbCloseArea() )
Return nil

Static Function MakeVars()
   nIdContact := 0 //Auto increment
   cName      := space(60)
return .T.

Static Function FieldsGet()
   nIdContact := ctc->idcontact
   cName      := ctc->name
   lAdd       := .F.
return .T.

Static function RefreshGets()
   oIdContact : Refresh()
   oName      : Refresh()
return .T.

Static function UpdateGets()
   FieldsGet()
   RefreshGets()
return .T.

Static function DelContact(oDlg,lSQL)
Local cSQl

   If lSQL
      cSQL := "DELETE FROM contacts WHERE idcontact = " + hb_ntos(ctc->idcontact)
      If rddInfo( RDDI_EXECUTE, cSQL )
         Hwg_msgInfo("Record deleted.")
         ctc->(dbCloseArea())
         dbUseArea( .T., , "SELECT * FROM contacts", "ctc" )
      Else
         Hwg_MsgStop("Fail erase record.")
      EndIf
   Else
      IF ctc->( RLOCK() )
         If ctc->(deleted())
            ctc->(dbRecall())
            hwg_MsgInfo("Record recovered.")
         Else
            ctc->(DbDelete())
            hwg_MsgInfo("Record deleted.")
         EndIf
      EndIf
   EndIf

   oDlg:oBrw:Refresh()

return .T.

Static Function NewContact()
   lAdd := .T.
   MakeVars()
   oIdContact:SetGet("New Contact")
   oIdContact:Refresh()
   oName:SetGet(cName)
   oName:SetFocus()
   hwg_edit_SetPos( oName:Handle, 1 ) //Set 1 position edit of get

return .T.

Static function SaveContact(oDlg,lSQL)
Local cSQL
   cName := oName:Value

   If empty(cName)
      hwg_msgStop("Please enter with a name")
      oName:SetFocus()
      hwg_edit_SetPos( oName:Handle, 1 ) //Set 1 position edit of get
      return .t.
   EndIf

   If lAdd

      If lSQL

         cSQL := "INSERT INTO contacts (name) values ('" + cName + "')"
         If rddInfo( RDDI_EXECUTE, cSQL  )
            ctc->(dbCloseArea())  //Close table contact
            dbUseArea( .T., , "SELECT * FROM contacts", "ctc" ) //need open contacts table becouse new data.
         Else
            hwg_msginfo('Fail to add data')
         EndIF

      Else

         ctc->( dbappend() )
         If NetErr()
            hwg_MsgStop("Error on append.")
            return .F.
         EndIf

      EndIf

   Else

      If lSQL
      Else
         If !ctc->(dbRLock())
            hwg_MsgStop("Error on replace.")
         EndIf
      EndIf

   EndIf

   If lSQL
      If lAdd
      Else
         cSQL := "UPDATE contacts SET name = '" + cName + "' WHERE idcontact = " + hb_ntos(ctc->idcontact)
         If rddInfo( RDDI_EXECUTE, cSQL  )
            Hwg_MsgInfo("contact: " + hb_ntos(ctc->idcontact) + " updated.")
            ctc->(dbCloseArea())
            dbUseArea( .T., , "SELECT * FROM contacts", "ctc" )
         Else
            Hwg_MsgStop("Fail contact update.")
         EndIf
      EndIf
   Else
      ctc->name := cName
   EndIf

   lAdd := .F.
   oDlg:oBrw:Refresh()

return .T.

Static Function DelOnOff(oDlg)
   Local lSetDeleted := Set( _SET_DELETED )
   iif(lSetDeleted, Set( _SET_DELETED, .F.), Set( _SET_DELETED, .T.) )
   oDlg:oBrw:Refresh()

return .T.

Function Contacts_MariaDB
   Local oDlg, oBrw, oTab, oFontDlg, oFontBrw //Controls of Dialog
   Local oBtnDel, oBtnSave, oBtnAdd, oBtnOnOff //Controls of Dialog
   Local nTab, lSQL := .T., nConnection
   Private nIdContact, cName, cPhantom := space(1)  //Fields of DataBase
   Private lAdd := .F.

   rddSetDefault( "SQLMIX" )
   nConnection := rddInfo( RDDI_CONNECT, { "ODBC", "Server=127.0.0.1;Driver={MariaDB};dsn=;User=itamar;password=@itamar;database=test;" } )

   IF nConnection == 0
      hwg_msgstop("Unable connect to server" +hb_eol() + rddInfo( RDDI_ERRORNO ) + hb_eol() + rddInfo( RDDI_ERROR ) )
      RETURN .F.
   ENDIF

    //hwg_msginfo("Number of conection:" + hb_ntos(nConnection))
    If !rddInfo( RDDI_EXECUTE, "CREATE DATABASE IF NOT EXISTS `test`" )
       Hwg_msginfo("Fail to create database test of MariaDB")
    EndIf
    If !rddInfo( RDDI_EXECUTE, "USE `test`" )
       Hwg_msginfo("Fail to conect on database test of MariaDB")
    EndIF

    dbUseArea( , , "SELECT COUNT(*) as nTot FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 'contacts' ",'RS' )
    nTab := rs->nTot
    rs->(dbCloseArea())

    If nTab > 0
       If hwg_MsgYesNo("Erase table contacts ?")
          If rddInfo( RDDI_EXECUTE, "DROP TABLE contacts" )
             nTab := 0
          Else
             hwg_MsgStop("Fail to erase table contacts.")
          EndIF
       EndIf
    EndIf

    If empty(nTab) //make table contacts
       If rddInfo( RDDI_EXECUTE, "CREATE TABLE contacts ( idcontact MEDIUMINT NOT NULL AUTO_INCREMENT, NAME CHAR(60) NOT NULL, PRIMARY KEY (idcontact) )" )
          Hwg_msginfo("Table contacts create on MariaDB")
       Else
          Hwg_msginfo("Fail to make table contacts")
       EndIf

       If rddInfo( RDDI_EXECUTE, "INSERT INTO contacts (name) values ('JOSÉ DE ASSUMPÇÃO'),('MARIA ANTONIETA'), ('SNOOPY'), ('POPEYE')" )
          Hwg_MsgInfo("Data add")
       Else
          Hwg_MsgInfo("Fail to add data.")
       EndIf
    EndIf

    dbUseArea( .T., , "SELECT * FROM contacts", "ctc" )

   PREPARE FONT oFontDlg NAME "Z003" Width 0 Height 16
   PREPARE FONT oFontBrw NAME "Courier" Width 0 Height 14

INIT DIALOG oDlg CLIPPER NOEXIT TITLE "Contacts using SQLMIX and MariaDB" AT 0,0 size 1024,500 Font oFontDlg STYLE DS_CENTER

   @ 10,080 browse oBrw DataBase Of oDlg size 360,400 Font oFontBrw ;
   On PosChange {|| UpdateGets() }

   oBrw:Alias:="ctc"

   Add Column {||iif(ctc->(Deleted()),"Yes","No" ) } to oBrw ;
   Header "Del" Length 3

   Add Column FieldBlock("idcontact") to oBrw ;
   Header "Cont_ID" Length 10

   Add Column FieldBlock("name") to oBrw ;
   Header "Name" length 100

   @ 370,005 Tab oTab Items {} size 600,430 of oDlg

      BEGIN PAGE "Contacts" of oTab

         FieldsGet()

         @ 010,010 GroupBox "ID" size 120,60
         @ 020,030 Get oIdContact var nIdContact Picture "9999999999" size 090,30 STYLE ES_RIGHT

         @ 010,080 GroupBox "Name" size 500,60
         @ 020,100 Get oName var cName size 470,30 //ToolTip "Name of contact"

         @ 020,160 Get oPhantom var cPhantom size 0,0 //Phantom get to validate last get

      END Page Of oTab

   @ 370,440 button oBtnSave   Caption "Save"   on click {||SaveContact(oDlg,lSQL)} size 90,50
   @ 470,440 button oBtnAdd    Caption "Add"    on click {||NewContact()}           size 90,50
   @ 570,440 button oBtnDel    Caption "Del"    on click {||DelContact(oDlg,lSQL)}  size 90,50
   @ 670,440 button oBtnOnOff  Caption "On Off" on click {||DelOnOff(oDlg)}         size 90,50

   oDlg:bActivate:={||oBrw:top(),oBrw:Refresh() }

oDlg:Activate()

ctc->( dbCloseArea() )
Return nil

Re: Harbour + SQLMIX

Enviado: 01 Mai 2026 22:39
por Itamar M. Lins Jr.
Olá!
Exemplos na pasta contrib(sdd...)
Neste caso no Mysql, mas tem até para Oracle(sddoci).

Código: Selecionar todos

~/dev/hb32/contrib/sddmy/tests$ cat test1.prg 
#require "rddsql"
#require "sddmy"

#include "dbinfo.ch"
#include "error.ch"

REQUEST SDDMY, SQLMIX

ANNOUNCE RDDSYS

FIELD RESIDENTS

PROCEDURE Main()

#if defined( __HBSCRIPT__HBSHELL )
   rddRegister( "SQLBASE" )
   rddRegister( "SQLMIX" )
   hb_SDDMY_Register()
#endif

   rddSetDefault( "SQLMIX" )

   AEval( rddList(), {| x | QOut( x ) } )

   IF rddInfo( RDDI_CONNECT, { "MYSQL", "localhost", "test", , "test" } ) == 0
      ? "Unable connect to the server"
      RETURN
   ENDIF

   CreateTable()

   ? "Let's browse table (press any key)"
   Inkey( 0 )
   dbUseArea( .T., , "SELECT * FROM country", "country" )
   Browse()

   ? "Let's browse table ordered by resident count (press any key)"
   Inkey( 0 )
   INDEX ON RESIDENTS TAG residents TO country
   Browse()

   dbCloseAll()

   RETURN

STATIC PROCEDURE CreateTable()

   ? rddInfo( RDDI_EXECUTE, "DROP TABLE country" )
   ? rddInfo( RDDI_EXECUTE, "CREATE TABLE country (CODE char(3), NAME char(50), RESIDENTS int(11))" )
   ? rddInfo( RDDI_EXECUTE, "INSERT INTO country values ('LTU', 'Lithuania', 3369600), ('USA', 'United States of America', 305397000), ('POR', 'Portugal', 10617600), ('POL', 'Poland', 38115967), ('AUS', 'Australia', 21446187), ('FRA', 'France', 64473140), ('RUS', 'Russia', 141900000)" )

   RETURN

Re: Harbour + SQLMIX

Enviado: 02 Mai 2026 12:35
por MSDN_7
Obrigado Itamar, agora a coisa anda, grande contribuição !

Re: Harbour + SQLMIX

Enviado: 02 Mai 2026 13:03
por MSDN_7
Fiz ajustes baseados nos teus códigos, e agora, quando incluo as informações via GET solicitado em tela, elas aparecem no TBrowse, ok, porém, mesmo após executar o INSERT INTO .... , não grava no banco, tem algum comando posterior que precisa ser acionado ?
OBS : Estou usando Oracle

Re: Harbour + SQLMIX

Enviado: 02 Mai 2026 13:10
por Itamar M. Lins Jr.
Olá!
Depois de incluir no SGBD precisa fechar e puxar de novo.

Código: Selecionar todos

If lAdd

      If lSQL

         cSQL := "INSERT INTO contacts (name) values ('" + cName + "')"
         If rddInfo( RDDI_EXECUTE, cSQL  )
            ctc->(dbCloseArea())  //Close table contact
            dbUseArea( .T., , "SELECT * FROM contacts", "ctc" ) //need open contacts table becouse new data.
         Else
            hwg_msginfo('Fail to add data')
         EndIF
...
Primeiro vc grava no SGBC. Se gravou só no DBF(array) não vai para o banco de dados.
Se aparece no DBF é pq funcionou.
Se tá no DBF pq não está no SGBD ? (MySQL) no caso.
Pq tá gravando só no DBF sem mandar para o SGBD.