Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 15-12-2008
Sick boy Sick boy is offline
Miembro
 
Registrado: may 2003
Ubicación: Cantabria
Posts: 245
Poder: 22
Sick boy Va por buen camino
Hola,

Al, muchas gracias por las molestias que te has tomado y las extensas respuestas (por cierto, mi nombre es Ricardo).

Utilizo sobre todo TMDOQuery, muchos de ellos los creo y libero en tiempo de ejecucion. Tambien utilizo TMDODataset, aunque muchos menos.

Si no entiendo mal, lo de una variable que se incremente seria algo como

Código Delphi [-]
function valor_contador_cursor:string;
begin
  // CODIGO BY Lepe
  miLong := (miLong  + 1 )
  if miLong > high(int64) -1 then
    miLong := low(int64);
  result:=inttostr(miLong);
end;

Ahora una pregunta tonta, ¿donde declaro la variable miLong? En el private de TMDOSQL??

Y le pasamos el valor al cursor:
Código Delphi [-]
FCursor := Name + valor_contador_cursor;
Dejo Name porque no me molesta, y se puede utilizar sabiendo que el name corresponde a QSelect.

Cita:
Si tu componente es un TMDODataSet, sería ejecutar algo como:

Código Delphi [-]

MDODataSet1.QSelect.Name := CadenaUnica;

Pero si es un TMDOQuery o TMDOTable, tendrás que usar el clásico truco de molde de tipo (type cast) para acceder a la propiedad QSelect, ya que en estas dos clases la propiedad permanece en ámbito protegido (no está redeclarada en la sección Public como en TMDODataSet):

Código Delphi [-]

Type
TMDOQueryAccess = Class (TMDOQuery);
...
Begin
TMDOQueryAccess (MDOQuery1).QSelect.Name := CadenaUnica;

Obviamente, esta acción debe ocurrir antes de que el método Prepare del objeto QSelect (TMDOSQL.Prepare) haga referencia a esa propiedad Name para formar el nombre del cursor.
Es justo a lo que me referia, gracias, no lo he probado, pero con esto se podría pasar un prefijo al cursor.

La rutina que esta en el timer realiza una encriptacion o desencriptacion de un string.
Código Delphi [-]
//encriptar datos
function encriptar(aStr: String; aKey: Integer): String;
begin
   Result:='';
   RandSeed:=aKey;
   for aKey:=1 to Length(aStr) do
       Result:=Result+Chr(Byte(aStr[aKey]) xor random(256));
end;

//desencriptar datos
function desencriptar(aStr: String; aKey: Integer): String;
begin
   Result:='';
   RandSeed:=aKey;
   for aKey:=1 to Length(aStr) do
       Result:=Result+Chr(Byte(aStr[aKey]) xor random(256));
end;
aKey es la "clave" para obtener los resultados, asi que siempre es la misma, con lo que el generador de numeros aleatorios se reinicia siempre (por lo que he entendido) con la misma secuencia de numeros.

A riesgo de parecer paranoico, si despues de utilizar estas funciones ejecuto un por ejemplo RandSeed(entero_no_repetido), donde "entero_no_repetido" haga honor a su nombre y sea distinto en cada ocasion.

La verdad, creo que lo mejor puede ser la idea de que el cursor sea un "contador" y olvidarse para siempre del tema de los numeros aleatorios.
Tener un error aleatorio que se propaga por todos los procedimientos de tu programa es una pesadilla. Si os preocupais por vuestros clientes y vuestro codigo no se lo deseo a nadie.

Última edición por Sick boy fecha: 15-12-2008 a las 11:11:24. Razón: Editado: result:=inttostr(miLong);
Responder Con Cita
  #2  
Antiguo 15-12-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Thumbs up

yo abandono el hilo, creo que tienes herramientas suficientes y de sobras para solucionarlo facilmente. Tansolo estamos desgastando polemica y confusión insertada. saludos y suerte.
Responder Con Cita
  #3  
Antiguo 15-12-2008
Sick boy Sick boy is offline
Miembro
 
Registrado: may 2003
Ubicación: Cantabria
Posts: 245
Poder: 22
Sick boy Va por buen camino
Ok Coso, gracias por tu ayuda.

A falta de las pruebas, esto esta solucionado, acabo de poner lo que comentaba Al González y me ha parecido perfecto, elegante y simple.

Siento la polemica sobre si los componentes son buenos, malos, bien escritos, etc....

Ojo, si piensas usar MDO, IBX y posiblemente FreeIB, deberias saber como los componentes generan el famoso cursor. De lo contrario, te puede pasar como a mi, y ante la falta de documentacion sobre el dichoso error 502, empiezas a probar soluciones de todo tipo sin encontrar el motivo de los errores.

Al final, declare la variable en MDOUtils, como una variable global cualquiera, iniciandola con el valor minimo del tipo integer (si, decidi usar integer, me parece más que suficiente).
En mi caso, el programa que hago no funciona ininterrupidamente, y cada vez que se reinicia el programa el contador empezara en el valor minimo de integer, y la verdad es que dudo de que en un solo dia consiga alcanzar los numeros positivos.
Tengo clientes que hibernan el equipo (yo mismo lo hago), hay veces que el ventanucos aguanta hasta 30 dias sin fallar. Dudo de que en 30 ó 60 dias se acaben los valores de integer, en cualquier caso, si sucede se reinicia el contador.
Al reiniciar el contador se podrian repetir los cursores de nuevo?? Claro, si empiezas otra vez se pueden repetir. En mi caso, un cursor nunca estará tanto tiempo activo (Al hablaba de años), asi que para mi es seguro.

Sobre que se conecten otros equipos clientes y consuman mi contador, no creo que eso suceda.
Evidentemente Al sabe más que yo, pero creo que en esto te equivocas, ya que el programa cliente que accede utilizará su propio contador, independiente en cada cliente. Y esto no nos importa porque los cursores deben de ser unicos en el ambito de la transaccion
Si me equivoco en esto decirmelo.

Quiero dejar el programa funcionando unos dias para ver que pasa, no quiero sorpresas, y despues postearé el codigo que he modificado, por si le sirve a alguen.
Al menos ahora, no tengo que preocuparme de numeros aleatorios.

Última edición por Sick boy fecha: 15-12-2008 a las 13:16:32.
Responder Con Cita
  #4  
Antiguo 15-12-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Si Al González confía en los GUID, para mí sobran las palabras. ¿Qué tal esto?:
Código Delphi [-]
procedure TForm1.FormCreate(Sender: TObject);
var
  guid:TGUID;
  strGuid:string;
begin
  CreateGUID(guid);
  try
    strGuid := GUIDToString(guid)
  except
    on EConvertError do
    begin
      strguid :=  FormatDateTime('yyyymmddhhmmsszzz',now) + RandomString(8);
    end;
  end;
  FCursor := strguid;
end;

Esto iría en el constructor del TMDOSQL. Puesto que lo usan internamente para las tablas de sistema, ya estaríamos usando el famoso GUID (salvo error en mi código).

Vaya, veo que Sick Boy ha implementado la solución, bueno, si falla, aquí tienes otra posibilidad.

Edito: Al final esto no me gusta. La ayuda de delphi dice que puede saltar el EConverterror al traducirlo a string y en ese caso estaríamos de vuelta con el RandomString. Muy posiblemente la solución del Integer sea la mejor.


Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.

Última edición por Lepe fecha: 15-12-2008 a las 12:14:26. Razón: Resumen final
Responder Con Cita
  #5  
Antiguo 15-12-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Pues a mi me gusta la opción de Al y la GUID. Aunque, ese arreglo que hace lepe al hacer uso de ambas cosas: GUID y numeros aleatorios.

Como yo he dicho: mucho no aporto, asi que será mejor que no opine mucho.

Lo que si es bueno comentar, viendo el código que empleas para cifrar (encriptar no es el término más adecuado), que no se emplee la función Random, RandomSeed o alguna relacionada con éstas para desarrollar algoritmos de cifrado. Si bien empleas RandSeed para generar la misma secuencia, las funciones Random no fueron diseñadas para mecanismos de criptografía, sino con fines de simulación, y/o estadísticos.

Además, la función Random cambia según la versión del compilador. Si luego adquieres una nueva versión del compilador, es posible que por más RandSeed que tengas, el resultado sea otro.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #6  
Antiguo 17-12-2008
Sick boy Sick boy is offline
Miembro
 
Registrado: may 2003
Ubicación: Cantabria
Posts: 245
Poder: 22
Sick boy Va por buen camino
Talking

Hola,

Hasta el momento, la modificacion ha funcionado correctamente.

Lo que hice fue lo siguiente:

1.- Añadir una variable MDO_Unique_Cursor en MDOUtils.pas
Código Delphi [-]
var
  MDO_Unique_Cursor: Integer = (aqui va el valor más bajo de un integer, ahora no lo recuerdo);

2.- Añadir la función (en MDOUtils) que incremente nuestra nueva variable.
Código Delphi [-]
function Valor_Cursor_MDO:string;
begin
  try
    inc(MDO_Unique_Cursor);
  except
    MDO_Unique_Cursor:= low(integer);
  end;
  result:= inttostr(MDO_Unique_Cursor);
end:
He utilizado un bloque try..except porque creo que será más rapido que un if..then..else. Ya me he equivocado un monton de veces en este hilo, puede que me equivoque en esto tambien.

3.- En MDOSQL.pas, buscar el TMDOSQL.Prepare, y sustituir la linea donde se asigna el valor al cursor por esta:
Código Delphi [-]
FCursor := Name + Valor_Cursor_MDO;

Si utilizas IBX o FreeIB, seria algo parecido, aunque yo comentaria la asignación del cursor en el .Create. Al ya ha explicado porque es mejor.

Aunque el valor de Name (haciendo un uso "normal" del componente TMDOQuery, TMDODataset) siempre es vacio, el cursor funciona sin problemas.
Supongo que el componente TMDOSQL si que pasará el valor de Name al crear el cursor. No lo he probado, y no lo necesito.

El typecast, al principio no me funcionaba, luego recorde que hay que hacerlo en la misma unit donde tengas los componentes, y asi si que funciona.

Como digo, Name no es necesario, salvo que seais capaces de acabaros todos los numeros integer en poco tiempo. Si este fuera el caso, recomendaria pasar el valor Name mediante un typecast, o con un overload del create como se sugiere en el foro.

La rutina para "cifrar" no contiene la formula de la coca cola , se trata solo de evitar que el usuario pueda cambiar algunas cosas.
Estas rutinas estan en la web por todas partes, yo no se si las vi por primera vez en trucomania.
Tienen varios inconvenientes, por ejemplo, el texto no siempre es legible, puede tener caractares no imprimibles, y si lo guardas a un archivo luego no es descifrable.
Admito sugerencias, pero como esto del cifrado deberia estar en otro hilo, enviarlas por privado, y si es necesario comentar algo iniciamos el post en el foro correspondiente.

No podeis imaginaros lo agradecido que estoy por la ayuda que desinteresadamente me habeis proporcionado. Ojalá algún dia tenga los conocimientos necesarios como para devolver(os) el favor.

GRACIAS
Responder Con Cita
  #7  
Antiguo 17-12-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Cita:
Empezado por Sick boy Ver Mensaje
He utilizado un bloque try..except porque creo que será más rapido que un if..then..else. Ya me he equivocado un monton de veces en este hilo, puede que me equivoque en esto tambien.
Perdona, equivocar, no te has equivocado, has utilizado una solución, que si bien podría no seguir algunos estándares de programación, funciona a la perfección.

En realidad las excepciones son costosas, ten en cuenta que ha de crearse un nuevo objeto en memoria, tracear la pila de llamadas y volver hacia atrás buscando los try ... except en toda la pila de llamadas y, si no encuentra ninguna más, entonces mostrar el mensaje al usuario.

El dicho viene al caso: "más vale prevenir que curar". Si puedes esquivar la excepción, mejor que mejor. Un "if ...else" sólo se traduce en una comparación y salto en ensamblador. La creación de la excepción, como ya he dicho, es algo más costoso que eso.

En tu favor, podemos decir que tu código funcionará perfectamente e incluso más rápido que ese "if ... else" porque ahorras esas dos instrucciones ensamblador. Sólo en el caso de superar el máximo número del tipo Integer, será un poco más lento tu código. Usando el "if...else" siempre tendrás la misma "velocidad de ejecución" (se supere el máximo o no).

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #8  
Antiguo 17-12-2008
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola amigos.

Que bueno que ya quedó resuelto el asunto de Ricardo, sólo habrá que esperar a ver si no hay más en juego. De cualquier forma, y gracias a esta discusión, hemos descubierto una deficiencia de consideración en la familia de los componentes IBX.

Quisiera agregar algo breve, sobre lo recién comentado.

Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
Var
  I :Integer;
  B :Byte;
begin
  I := MaxInt;
  Inc (I);  // O "I := I + 1;"
  ShowMessage (IntToStr (I) + ' = ' + IntToStr (Low (Integer)) +
    ' (el incremento de enteros es circular).');

  B := MaxByte;
  Inc (B);  // O "B := B + 1;"
  ShowMessage (IntToStr (B) + ' = ' + IntToStr (Low (Byte)) +
    ' (el incremento de enteros es circular).');
end;

El código anterior demuestra que no es necesaria ninguna implementación especial cuando se quiere hacer incremento circular de una variable de tipo entero, alcanzando todos sus valores posibles.

Un saludo.

Al.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Mensaje de error extraño Sick boy Firebird e Interbase 0 12-12-2008 11:22:26
Error Extraño SysAdminGCS Varios 1 18-08-2007 16:30:49
Error Extraño Esau SQL 4 17-06-2005 22:44:16
error extraño gilberto_1126 Varios 2 05-09-2004 01:01:01
Error Extraño Esau OOP 5 19-11-2003 18:01:32


La franja horaria es GMT +2. Ahora son las 22:18:55.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi