Jump to content
Fivewin Brasil

SQLRDD - SR_CHANGESTRUCT


macs

Recommended Posts

Boa tarde pessoal,

Estou com problema ao realizar a alteração de estrutura de uma tabela utilizando a função Sr_ChangeStruct() com MySql

O log de alteração que é gerado é esse:

09/03/2021 12:09:25: TIPO_EXAME    Warning: DROP COLUMN:    BACKUP_    (1091) Can't DROP 'backup_'; check that column/key exists - Can't DROP 'backup_'; check that column/key exists    

Eu acho que é criado este campo BACKUP_ automático, pois na estrutura da tabela não existe este campo. 

Qualquer alteração de estrutura de qualquer tabela, gera este erro, e o pior que este campo (backup_) é criado na tabela.

Gostaria de saber se alguém já passou por isso.

Obrigado pela atenção!

 

 

Link to comment
Share on other sites

Já passei por isso.

renomeia essa coluna para o nome original que era antes da mudança em vez de deletar a coluna, e depois roda novamente a criação/alteração da estrutura para que o SALRDD consiga novamente criar essa coluna de backup e migrar os dados para a nova coluna que será criada.

Link to comment
Share on other sites

Mesma versão que uso aqui.

Isso acontece quando está alterando algum campo já existente. No meu caso acontecia quando estava alterando uma estrutura e, alguem entra no sistema consultando/alterando registro da mesma tabela que está sendo alterado a estrutura. Para resolver isso antes de começar a mudar a estrutura uso: SR_SetFastOpen(.F.) e depois que terminou de alterar mudo novamente para: SR_SetFastOpen(.T.)

Link to comment
Share on other sites

Em 13/03/2021 at 11:58, mkyx disse:

Bom dia, eu uso o alter table, sem problemas, com sqlrdd.

Eu gostaria que o RDD ficasse responsável por fazer qualquer tipo de manutenção nas tabelas. Se existe a função, ela teria que funcionar.

Sei que a maioria dos comandos são iguais para qualquer banco de dados, mas eu não gostaria de ficar testando se o banco é ORACLE, ou Postgres, MySql, etc. Provavelmente o SQLRDD está prevendo todas as situações.

Provavelmente deve ser a versão que estou utilizando. Alguém com versão mais recente poderia testar a função. Valeu!

Link to comment
Share on other sites

Em 13/03/2021 at 10:07, sygecom disse:

Mesma versão que uso aqui.

Isso acontece quando está alterando algum campo já existente. No meu caso acontecia quando estava alterando uma estrutura e, alguem entra no sistema consultando/alterando registro da mesma tabela que está sendo alterado a estrutura. Para resolver isso antes de começar a mudar a estrutura uso: SR_SetFastOpen(.F.) e depois que terminou de alterar mudo novamente para: SR_SetFastOpen(.T.)

Não existe outra pessoa utilizando, está acontecendo em minha base de dados. Mesmo assim vou testar conforme informado!

Link to comment
Share on other sites

Eu uso e também tive problema com Sr_ChangeStruct(), por isso criei minha própria função. Segue. Espero que ajude.

   aStr:={}
   AADD(aStr,{"CODIGO",    "C", 13,  0}) // Código do item
   AADD(aStr,{"DESCRI",    "C",120,  0}) // Descrição do item (No SISCOM só pega 60 caracteres)
   AADD(aStr,{"DTEXCL",    "D", 08,  0}) // Data da exclusão - Para determinar quando eliminar deste bd, ex: 7 dias após a exclusão.
   l_Reindex := .F.
   IF ! SR_ExistTable( "itensdel_bd" )
      TRY
         cComm := XB2SqlStr(aStr, "itensdel_bd")
         nErr := oSql:Execute( cComm )
      CATCH oErr
         SysRefresh()
         MsgAlert("Erro ao tentar criar a tabela itensdel_bd."+CRLF+CRLF+;
                  "Favor verificar as configurações de banco de dados.","Erro")
         IF FileWrite(ErroFile(), oErr:Description)
            WAITRUN( GetEnv( "ComSpec" )+" /C NOTEPAD .\errorlog\erro.txt", 0)
         ENDIF
         PostQuitMessage( 0 )
         __QUIT()
      END
   else
      ChkStruct("itensdel_bd", "", "", aStr, oSql, nErr, nPos)
   ENDIF


STATIC FUNCTION XB2SqlStr(aStr, cDBase)
   LOCAL cStrct
   cStrct := "CREATE TABLE `"+LOWER(cDBase)+"` ("
   FOR nF := 1 TO LEN(aStr)
   	 IF LOWER(aStr[nF,1]) !=  "sr_recno"
	       IF nF > 1 ; cStrct += ", " ; ENDIF // Mais de um campo
	       cStrct += "`"+LOWER(aStr[nF,1])+"` "+SetFType(aStr[nF,2],aStr[nF,3],aStr[nF,4])
       ENDIF
   NEXT
   IF LEN(aStr) > 0 ; cStrct += ", " ; ENDIF // Já acrescentado algum campo
   cStrct += "`sr_recno` BIGINT (15) NOT NULL UNIQUE AUTO_INCREMENT)" // Sempre criar o 'sr_recno' no final, para compatibilizar com SQLRDD
RETURN( cStrct )

STATIC FUNCTION SetFType(cTipo,nSize,nDeci)
   LOCAL cFType
   IF cTipo = "C" ; cFType := "char("+ALLTRIM(STR(nSize))+")"
   ELSEIF cTipo = "M" ; cFType := "mediumblob"
   ELSEIF cTipo = "N" ; cFType := "double("+ALLTRIM(STR(nSize))+","+ALLTRIM(STR(nDeci))+")"
   ELSEIF cTipo = "L" ; cFType := "tinyint(4)"
   ELSEIF cTipo = "D" ; cFType := "date"
   ENDIF
RETURN(cFType)

STATIC FUNCTION ChkStruct(cTable, cUniq, cAuto, aStrct, oSql, nErr, nPos)
   LOCAL lChangd, cComm, aNewStr, aOldStr, aChange, aImport, cImport, aArray := {}, cTmpTable := cTable+"_old"
   IF ! l_CkStr ; RETURN .F. ; ENDIF // Não deve verificar a estrutura dos dados. Apenas criar as novas tabelas
   cDBName := UPPER( SR_GetConnectionInfo(, SQL_DBMS_NAME ) )
   IF ! ("FIREBIRD" $ cDBName) // Não estou conectado ao Firebird. Firebird não aceita RENAME TABLE - http://www.firebirdfaq.org/faq363/
      aNewStr := aStrct
      nScan := ASCAN(aNewStr, {|nC|nC[1]="sr_recno"})
      IF nScan = 0
   	   AADD(aNewStr, {"sr_recno", "N", 15, 0}) // SQLRDD acrescenta este campo ao criar a tabela
      ENDIF

      cSay := "Verificando a tabela '"+cTable+"'"
      oSay:SetText(cSay) ; oSay:Refresh()

      IF ! l_CkStr ; RETURN .F.; ENDIF

      // Obter a estrutura da tabela atual.
      nLenTb := 0
      STORE 0 TO nErr, nPos
      TRY
         cComm := "SELECT * FROM "+cTable+" LIMIT 1"
         oSql := SR_GetConnection()
         nErr := oSql:execute( cComm )
         oSql:iniFields(.f.)
         aOldStr := oSql:aFields // Para pegar a estrutura
         nLenTb := LEN(aArray)
         * MyXBrowse(aOldStr, "Estrutura atual")
      CATCH
         SysRefresh() ; MsgAlert("Não foi possível testar a tabela '"+cTable+"'", +ProcName()+"("+AllTrim(Str(ProcLine()))+")")
         RETURN .F.
      END TRY

      // Comparar com a estrutura de aStrct
      lChangd := .F.
      aChange := {}
      aImport := {}
      cImport := ""
      TRY
         FOR nX := 1 TO LEN(aNewStr) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum.
             cFild:=Lower(aNewStr[nX,1])
             cType:=aNewStr[nX,2]
             cSize:=STRZERO(aNewStr[nX,3], 4)
             cDeci:=STRZERO(aNewStr[nX,4], 3)
             nElem := ASCAN(aOldStr, {|aNro| Lower(aNro[1]) == cFild})
             IF nElem > 0
             	 if cFild != "sr_recno" // Não considerar erro de estrutura deste
   	             IF cType != aOldStr[nElem,2] .OR. ;
   	                cSize != STRZERO(aOldStr[nElem,3], 4) .OR. ;
   	                cDeci != STRZERO(aOldStr[nElem,4], 3)
   	                lChangd := .T. // Mudou o tamanho de um campo
   	                aadd(aChange, {cFild, "Modificou a estrutura"})
   	             ENDIF
                endif
             ELSE
                lChangd := .T. // Foi removido algum campo
                aadd(aChange, {cFild, "Campo acrescentado"})
             ENDIF
         NEXT
         FOR nX := 1 TO LEN(aOldStr) // Verifica se foi excluindo algum compo
             cFild := Lower(aOldStr[nX,1])
             nElem := ASCAN(aNewStr, {|aNro| Lower(aNro[1]) == cFild})
             IF nElem = 0
                lChangd := .T. // Algum campo foi removido
                aadd(aChange, {cFild, "Campo removido"})
             ELSE
                AADD(aImport, cFild) // Para pegar só os campos que existem nas duas tabelas.
             ENDIF
         NEXT
         IF lChangd
            // Determinar quais campos serão importados da tabela temporária
            FOR nX := 1 TO LEN(aImport)
                IF Lower(aImport[nX]) != "sr_recno" // Apenas um teste
                   IF ! EMPTY(cImport) ; cImport += ", " ; ENDIF
                   cImport += aImport[nX] // Pegar só os campos que existem nas duas tabelas.
                ENDIF
            NEXT
         ENDIF
      CATCH
         SysRefresh() ; MsgAlert("Não foi possível testar a tabela '"+cTable+"'", +ProcName()+"("+AllTrim(Str(ProcLine()))+")")
         RETURN .F.
      END TRY

      IF ! lChangd ; RETURN .F. ; ENDIF

      IF SR_ExistTable( cTmpTable )
         cComm := "DROP TABLE "+cTmpTable
         TRY
            nErr := oSql:Execute( cComm )
            if nErr == 0
               SysRefresh() ; MsgAlert("Executou "+cComm, "Ok")
            else
               MsgAlert("Não foi preciso executar "+cComm, "Retorno: "+cValToChar(nErr))
            endif
         CATCH
            SysRefresh() ; MsgAlert("Não foi possível excluir a tabela '"+cTmpTable+"'", "Erro...")
            RETURN .F.
         END TRY
      ENDIF

      cComm := "ALTER TABLE "+cTable+" RENAME "+cTmpTable
      nErr := oSql:Execute( cComm )

      l_Err := .F.
   	TRY
         cComm := XB2SqlStr(aStrct, cTable)
         nErr := oSql:Execute( cComm )
      CATCH oErr
   	   l_Err := .T.
      END TRY
      IF l_Err
   	   cComm := "ALTER TABLE "+cTmpTable+" RENAME "+cTable
   	   nErr := oSql:Execute( cComm )
         MsgAlert("Erro ao tentar criar a nova a tabela: Executado RollBack '"+cTable+"'.","Erro") ; SysWait(1)
         RETURN .F.
      ENDIF
      IF ! EMPTY(cUniq)
         TRY
            cSql := "ALTER TABLE "+cTable+" ADD UNIQUE ("+cUniq+")"
            nErr := oSql:Execute(cSql)
         CATCH
         END TRY
      ENDIF
      IF ! EMPTY(cAuto)
         TRY
            cSql := "ALTER TABLE "+cTable+" MODIFY "+cAuto+" int NOT NULL AUTO_INCREMENT"
            nErr := oSql:Execute(cSql)
         CATCH
         END TRY
      ENDIF
      // Importar dados da tabela temporária
      IF ! empty(cImport)
         cComm := "INSERT INTO "+cTable+" ("+cImport+") SELECT "+cImport+" FROM "+cTmpTable
         nErr := oSql:Execute( cComm )
         IF nErr != 0
            MsgAlert("Erro ao tentar recuperar os dados da tabela '"+cTmpTable+"'.","Erro") ; SysWait(0.5)
         ENDIF
      ENDIF
      // Excluir a tabela temporária
      cComm := "DROP TABLE "+cTmpTable
      nErr := oSql:Execute( cComm )
   ELSE // Estou usando Firebird, que não aceita RENAME TABLE - http://www.firebirdfaq.org/faq363/
      USE &(cTable) EXCLUSIVE VIA "SQLRDD"
      a_Str := dbStruct()
      lChangd := .F.
      IF LEN(a_Str) != LEN(aStrct)
         lChangd := .T. // Campos foram removidos ou acrescentados
      ELSE
         FOR nRow := 1 TO LEN(a_Str) // Verifica se foi acrescentado algum campo ou se mudou o tamanho de algum.
             cFld := Lower(a_Str[nRow,1])
             cTyp := a_Str[nRow,2]
             cSze := STRZERO(a_Str[nRow,3], 4)
             nDec := ALLTRIM(STR(a_Str[nRow,4]))
             nElem := ASCAN(aStrct, {|aNro| UPPER(ALLTRIM(aNro[1])) == UPPER(ALLTRIM(cFld))})
             IF nElem > 0
             	 IF UPPER(cFld) != "SR_RECNO" // Não considerar erro de estrutura deste
   	             IF cTyp != aStrct[nElem,2] .OR. ;
   	                nDec != ALLTRIM(STR(aStrct[nElem,4])) // Não verificar nSize em campos numéricos no Firebird. Tamanho fixo: 19
   	                lChangd := .T. // Mudou a estrutura
   	             ENDIF
   	             IF cTyp == "C" .AND. cTyp == aStrct[nElem,2]
                      IF cSze <> STRZERO(aStrct[nElem,3], 4) // Considerar tamanho em campos tipo caractere
      	                lChangd := .T. // Mudou a estrutura
   	                ENDIF
   	             ENDIF
                ENDIF
             ELSE
                lChangd := .T. // Campo renomeado, ou houve exclusão de um e inclusão de outro.
             ENDIF
         NEXT
      ENDIF
      IF lChangd
         IF ! SR_ChangeStruct(cTable, aStrct) // Via SR_ChangeStruct(), indexes are automatically dropped if columns change
            lChangd := .F.
            SysRefresh() ; MsgAlert("Houve um erro ao tentar modificar a estrutura de "+cTable,"Aviso")
         ENDIF
      ENDIF
      dbCloseArea()
   ENDIF
RETURN( .t. )

*----------( Compara dois arrays e retorna .T. se houver diferença )----------*

FUNCTION ArrayCheck(aArr1, aArr2)
   LOCAL cArr1 := "", cArr2 := "", cNew := "", cOld := ""
   LOCAL _lDif := .F.; _aAdd := {}; _aDif := {}; _aDel := {}
   FOR n1 := 1 TO LEN(aArr1)
       aLin := aArr1[n1]
       cNew := ""
       cOld := ""
       if ! empty(cNew) ; cNew += CRLF ; ENDIF
       FOR nL := 1 TO LEN(aLin)
           cArr1 += ALLTRIM(CStr(aLin[nL]))
           cNew += ALLTRIM(CStr(aLin[nL]))
       NEXT
       n_Id := aArr1[n1,1]
       aOld := {}
       nScn := ASCAN(aArr2,{|nCel|nCel[1]==n_Id})
       IF nScn > 0 // Se achar, verificar se houve modificação
          aOld := aArr2[nScn]
          if ! empty(cOld) ; cOld += CRLF ; ENDIF
          FOR nL := 1 TO LEN(aOld)
              cOld += ALLTRIM(CStr(aOld[nL]))
          NEXT
       ELSE // Senão, foi excluído
          AADD(_aDel, aLin) // Gerar linha com o registro excluido
       ENDIF
       IF cNew != cOld
          AADD(_aDif, aLin) // Gerar linha com o registro modificado
       ENDIF
   NEXT
   FOR n2 := 1 TO LEN(aArr2) // Processar anteriores só para determinar se houve exclusão.
       aLin := aArr2[n2]
       FOR nL := 1 TO LEN(aLin)
           cArr2 += ALLTRIM(CStr(aLin[nL]))
       NEXT
       n_Id := aArr2[n2,1]
       nScn := ASCAN(aArr1,{|nCel|nCel[1]==n_Id})
       IF nScn = 0 // Se não achar, foi acrescentado
          AADD(_aAdd, aLin)
       ENDIF
   NEXT
   IF LEN(_aAdd) > 0 .OR. LEN(_aDif) > 0 .OR. LEN(_aDel) > 0
      _lDif := .T.
   ENDIF
   IF _lDif
      cInfo := "Houve alteração de item"
      IF LEN(_aDif) > 0
         cInfo += CRLF+CRLF+"Item diferente: "+CRLF
         FOR nL := 1 TO LEN(_aDif)
             aLin := _aDif[nL]
             FOR nC := 1 TO LEN(aLin)
                 cInfo += ALLTRIM(CStr(aLin[nC]))
             NEXT
             cInfo += CRLF
         NEXT
      ENDIF

      IF LEN(_aAdd) > 0
         cInfo += CRLF+CRLF+"Item novo: "+CRLF
         FOR nL := 1 TO LEN(_aAdd)
             aLin := _aAdd[nL]
             FOR nC := 1 TO LEN(aLin)
                 cInfo += ALLTRIM(CStr(aLin[nC]))
             NEXT
             cInfo += CRLF
         NEXT
      ENDIF

      IF LEN(_aDel) > 0
         cInfo += CRLF+CRLF+"Item excluido: "+CRLF
         FOR nL := 1 TO LEN(_aDel)
             aLin := _aDel[nL]
             FOR nC := 1 TO LEN(aLin)
                 cInfo += ALLTRIM(CStr(aLin[nC]))
             NEXT
             cInfo += CRLF
         NEXT
      ENDIF
   ENDIF
RETURN _lDif

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...