Condigo Sequencial

Fórum sobre a linguagem CA-Clipper.

Moderador: Moderadores

Josmar dos Santos
Usuário Nível 3
Usuário Nível 3
Mensagens: 277
Registrado em: 11 Jan 2006 18:36
Localização: Botucatu-SP

Condigo Sequencial

Mensagem por Josmar dos Santos »

Código: Selecionar todos

 FUNCTION SALVAR02(TIPO_ACAO)
02	LOCAL IRetorno := .F.
03	IF TIPO_ACAO = INCLUSAO
04	   CLIENTES->(Dbappend())
05	   cCODIGO := alltrim( STRZERO( PSQCONTROLE( "clientes" ), 5 ))
06	   if cCODIGO="00000"
07	      ALERT("Ocorreu um erro na efetiva‡Æo do CODIGO SEQUENCIAL")
08	      RETURN .F.
09	   ENDIF
10	   CLIENTES->CODIGO := cCODIGO
11	   ALERT("Numero gerado no arquivo: " +cCODIGO)
12	ELSE
13	   CLIENTES->(RLOCK() )
14	ENDIF
15	IF .NOT. NETERR()
51	   CLIENTES->( DBCOMMIT() )
52	   CLIENTES->( DBUNLOCK() )
53	ELSE
54	   ALERT("Falha ao incluir novo cliente")
55	endif
56	return .t.  

Bom dia Rochinha. Estou usando essa mesma rotina para gerar o código sequencial com a sua função PsqControle. O código não voltou aos valores anteriores como eu já havia mencionado acima, mas não está pulando, ou seja, ele registra por exemplo: sempre o valor 33.000.

Deu erro de sintaxe nesse comando:
DEFAULT _altera_ := .t., _ComValor_ := 0
Para mim dentro da minha ignorância está correto, mas o compilador não gostou.
É pessoal, admiro vocês que já estão na estrada a tando tempo porque confesso a vocês, não está sendo fácil para mim!!!! , mas sou Brasileiro não desisto nunca...rs.rs.rs.rs
:%

Josmar
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Condigo Sequencial

Mensagem por JoséQuintas »

Se olhar direito, a pesqcontrole inicia a contagem com RecCount() + RecCount() / 4
Isso vai ser 50% a mais do que a quantidade de registros.

Se olhar direito também, não pode usar REPLACE direto, já que a rotina pode falhar e retornar valor zero, ou até esse número acima em determinada situação.

Tem que considerar que a rotina é exemplo, não é só colocar no seu programa e pronto.
Tem que ajustar pra suas rotinas de rede, pra considerar falhas no programa que usa a rotina, etc.
Até mesmo conflito de nome de variáveis usadas na rotina.

Tá aqui uma versão mais próxima do que eu uso:

Código: Selecionar todos

FUNCTION ProximoCodigo( cDbf, lSeek )
   LOCAL nCodigo, nSelect, acStructure

   nSelect := Select() // salva a área atual
   lSeek   := iif( lSeek == NIL, .T., lSeek )

   IF Select( "CONTROLE" ) == 0
      IF .NOT. File( "CONTROLE.DBF" )
         acStructure := { { "DATABASE" , "C", 12, 0 } , { "CONTADOR" , "N", 10, 0 } } // pra que economizar. Deixa tamanho 10 e tá pronto pro futuro
         SELECT 0 // só por garantia
         dbCreate( "CONTROLE", acStructure )
      ENDIF
      SELECT 0
      USE CONTROLE SHARED
   ENDIF

   SELECT ( Select( "CONTROLE" ) ) // SELECT é comando, e Select() é função
   LOCATE FOR UPPER( controle->Database ) = UPPER( cDbf )
   IF Eof()
      APPEND BLANK
      REPLACE controle->Database WITH cDBF, controle->Contador WITH 1
      SKIP 0
      UNLOCK
   ENDIF
   DO WHILE .NOT. RLock()
      InKey(0.5) // aguarde, não vai querer travar o computador ou sobrecarregar a rede tentando bloquear o registro
   ENDDO
   SKIP 0 // depois que conseguiu bloquear o registro, atualiza informação pra ver se mudou
   nCodigo := controle->Contador
    IF lSeek // se é pra pesquisar se existe, então pesquisa
      SELECT ( nSelect )
      DO WHILE .T.
         SEEK nCodigo
         IF Eof()
            EXIT // se não existe, então achou código disponível
         ENDIF
         nCodigo += 1
      ENDDO
   ENDIF
   SELECT CONTROLE
   REPLACE controle->Contador WITH nCodigo + 1 // deixa gravado como disponível o seguinte, e não o que vai usar agora
   SKIP 0 // antes de liberar, deixa atualizado
   UNLOCK // ok, atualizado libera, antes disto não, porque primeiro tem que achar o código e ter certeza de que ninguém mais vai usar
   SELECT ( nSelect )
   RETURN nCodigo // ok, aqui é o atual que não existe
Notas:
- Não usava COMMIT no Clipper, e continuo não usando no Harbour.
- Usando ou não o código retornado, ele vai ser desprezado, então pode acontecer de pular um número.
- Montei a rotina na hora de postar, apenas como exemplo, revise, só usei compilação -w3 -es2 pra não errar nomes de variáveis.
- Estou considerando que está usando Clipper 5.x
- Não se esqueça de passar .F., caso não queira confirmação de registro já existente

A idéia é: pega o próximo número, com a opção de verificar no arquivo original se já existe, mas o arquivo original precisa estar indexado por essa chave, e precisa ser numérica (a não ser que altere esta rotina).
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Josmar dos Santos
Usuário Nível 3
Usuário Nível 3
Mensagens: 277
Registrado em: 11 Jan 2006 18:36
Localização: Botucatu-SP

Condigo Sequencial

Mensagem por Josmar dos Santos »

Fiz algumas alterações na função inserindo alguns comandos de redes e o mesmo já está funcionando. Agora aguardar alguns dias para ver se não vai dar problemas...obrigado a todos


Josmar


:{
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Código Sequencial

Mensagem por JoséQuintas »

Faltou eu dizer:

No tempo do Clipper, eu NÃO usava o arquivo de controle de numeração.
Era raro ter problema - talvez 2 vezes num ano.
Usava BOTO BOTTOM, Codigo = Ultimo + 1
Mas também a rotina do SEEK, pra confirmar se estava em uso.

Quando passei pro Harbour, tive que usar o arquivo de controle.

Ao acontecer isso na migração pra Harbour, a primeira coisa é pensar no Harbour fazendo errado.
Mas se pega o último + 1, devia ser comum número repetido com muitos usuários fazendo inclusão.
Hoje em dia me pergunto como é que isso funcionava no Clipper sem o arquivo de controle.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4664
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Condigo Sequencial

Mensagem por rochinha »

Amiguinhos,

Só complementando, o SET DEFAULT é uma melhoria na facilidade de criticar os parâmetros passados pelas funções.

Um Set Default critica equivale a iif( critica, RetornaAlgoComoSendoPadrao, RetornaOValorDoParamentroPassado ).
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.

@braços : ? )

A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Condigo Sequencial

Mensagem por JoséQuintas »

O rochinha deve estar se referindo ao comando DEFAULT
Se não me engano, ele é definido num #include, e apenas facilita digitação, já que é substituído pelo iif().
Usando uma função, reduz código e reduz o EXE.

Código: Selecionar todos

Default( @variavel, 5 )

FUNCTION Default( xVariavel, xValor )
   xVariavel := iif( xVariavel == NIL, xValor, xVariavel )
Pode até criar com o mesmo nome existente no Harbour, assim já acostuma pra quando trocar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Condigo Sequencial

Mensagem por Eolo »

Quando passei pro Harbour, tive que usar o arquivo de controle.

Ao acontecer isso na migração pra Harbour, a primeira coisa é pensar no Harbour fazendo errado. Mas se pega o último + 1, devia ser comum número repetido com muitos usuários fazendo inclusão. Hoje em dia me pergunto como é que isso funcionava no Clipper sem o arquivo de controle.
Eu sempre usei (e ainda uso) o “último + 1”, no Clipper e no Harbour, mas embaixo de um Flock(), e nunca tive nenhum problema com chaves repetidas, só com “gargalos” no processamento (ver abaixo).

Como exemplo, tive um cliente, uma loja de materiais de construção, 6 terminais emitindo pedidos ao mesmo tempo, isso no Summer e NTX: cada usuário entrava com os dados do pedido (ainda sem a chave = o número do pedido) e, na hora de gravar, eu rodava o Flock(), gerava e gravava a próxima chave, COMMIT e aí liberava o DBF pra um próximo usuário / chave. Isso feito, ia gravar os demais dados do pedido, agora com o Rlock(). Gargalo? Sim, o DBF ficava “Flockado” por coisa de 2 segundos...

Um preço (em tempo) barato pra nunca ter problemas com chaves.

Enfim, pode não ser a maneira tecnicamente mais avançada de fazer a coisa, mas pra mim sempre resolveu e continua resolvendo.
Responder