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 14-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
Ole, no se por donde empezar.

Cita:
1. El nombre de un componente (propiedad Name) es una cadena vacía durante su construcción. A menos que el constructor realice, directa o indirectamente, una asignación de valor a la propiedad Name, no tiene sentido usarla como parte de una expresión dentro del constructor.
Ayer ya me di cuenta (le puse un showmessage al crear el cursor) de que la propiedad Fname no tiene ningun valor. Salvo que haya otro punto donde se creen los cursores, Fname es vacio tanto si creas el objeto en diseño o en ejecucion. Por lo tanto, todos los cursores son numeros de 8 digitos.

Efectivamente, el prefijo Fname ayudaria mucho a crear cursores unicos.

Cita:
Los creadores de MDO movieron la sentencia al método Prepare, con el argumento de "if you create the MDOSQL dynamically, the name is not assigned in the create and the cursor is only based on a 'random' number". Es claro que se dieron cuenta de lo mismo que comenté anteriormente (desde X versión de Delphi, o quizá desde siempre, la propiedad Name no tiene valor durante la ejecución del constructor). Pero asumen, o dan por recomendado, que debe asignarse un valor a la propiedad Name del objeto antes de ejecutar la consulta para que el nombre del cursor quede más rico y sea menos probable que se repita, lo cual es sencillo si el componente es agregado en tiempo de diseño o lo instanciamos nosotros mismos y enseguida le damos valor a Name. Sin embargo, la clase común TMDOCustomDataSet, al igual que sucede en los IBX, crea varias instancias internas de estos objetos SQL sin darles valor a su propiedad Name (a no ser que lo haga en algún punto del código que no logro ver). Así pues, con el nombre del cursor (FCursor) generado en el constructor Create o en el método Prepare, éste siempre será un número de 8 dígitos, a menos que se trate de un componente TMDOSQL que nosotros mismos hayamos preparado.
Bueno, me dices que name deberia tener un valor en componentes creados en tiempo de diseño, pero estoy casi seguro de que no es asi, los cursores siempre son 8 digitos. Voy a ver si consigo darle valor a Name, creo que seria una buena solucion.

He seguido investigando en el codigo MDO, y veo que TMDOSQL no tienen por ninguna parte la propiedad Fname, mientras que la clase TMDOXSQLVar si que la tiene. Por lo que veo es la unica clase con esa propiedad.

Por ahora, no veo la forma de darle valor a Name, creo que esto mejoraria la situacion.

Acabo de pasar el randomString(1), es decir, los cursores son un numero de un digito, name sigue siendo nulo. Como era de esperar la aplicacion arranca con problemas, pero ya puedo reproducir el error facilmente.

Cita:
Cita:
Empezado por Sick boy Ver Mensaje
...Por otro lado, si el problema no es por la generacion del numero de cursor, entonces es que un cursor se queda "pillado", pero no se como puede ser posible...
Eso necesitaría de otra línea de investigación. Pero dinos una cosa: en las máquinas donde falla, ¿cuántas veces por día u hora tu programa realiza una consulta Select sobre la base de datos? Una cifra estimada.
La pregunta es ¿cuantas veces abre el mismo Select? o ¿cuantos select/insert/... se realizan??
En este caso, el cliente realiza un uso bajo de la aplicacion, hay clientes que le superan por mucho.
Aproximado, no se, quizas 500 sentencias por hora. Algunas de las operaciones habituales requieren unos 6 cursores.

Cita:
P.D. Algo más: ¿alguien conoce el ámbito que tienen los nombres de cursores? ¿Es por conexión (programa), por máquina cliente, globales para todos los clientes...? Pienso que deberían ser por conexión/transacción, pero quisiera confirmarlo.
No estoy seguro, pero ahora que tengo cursores de un digito, te puedo indicar que el cursor 1 puede habrirse 3 veces seguidas sin problemas, y quizas la cuarta de el error, asi que debe ser a nivel de transaccion, o me daria el error al salir la segunda vez.

Acabo de descubrir algo interesante.
Le he puesto transaction.name y sql.text al showmessage que me indicaba cuando un cursor nuevo es creado. Tambien he puesto un showmessage para ver los cursores que no son nuevos. Los cursores son de 1 digito.
Los cursores reutilizados funcionan bien.
Los cursores nuevos, nunca tienen nombre, y parece que el ambito es la transaccion, ya que si haces un comit, la proxima vez que se abre el cursor aparece como NUEVO y le asigna un nuevo numero sin problemas. Diferentes transacciones y mismos numeros hasta ahora todo bien.

La sorpresa es que los select internos tipo "Select F.RDB$COMPUTED_BLR, F.RDB$DEFAULT_VALUE ....." no llevan asignado un nombre de transaccion.
Cuando comienzan a abrirse estos cursores, en pocas sentencias se produce el error, por ejemplo, detecta que el cursor 1 ya esta declarado y salta la excepcion. Cada vez que vuelva a aparecer ese cursor 1 en la transaccion "sin nombre" saltará el error.
He puesto un timer que repite una sentencia SQL simple, el select mio se ejecuta bien en la transaccion que tiene asignada. Al ejecutar la sentencia interna que te devuelve los valores por defecto, campos calculados, .... el cursor asignado en los 10 ultimos select ha sido el 1 (poco aleatorio, pero bueno) y cada vez que sale el 1 da error en ese select, no en el mio.
Si aleatoriamente sale un numero distinto del 1 la sentencia funciona correctamente.

Si cierras la aplicacion y la vuelves a abrir comienza todo, por lo que creo que el ambito del cursor es a nivel de transaccion/conexion.
Responder Con Cita
  #2  
Antiguo 14-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
Cita:
Te pido disculpas anticipadas y espero no te lo tomes a mal Sick boy, pero echa una visual por ejemplo al código fuente de la JVCL y lo verás lleno de "todo's", preguntas del estilo "¿esto dará fallo?" y lo más gracioso:"not implemented yet" en propiedades que tienes en el inspector de objetos y frases aún peores. Lo que quiero que comprendas es que un componente estable no significa "finalizado", e incluso uno "finalizado" no quiere decir que funcionará por tiempo ilimitado, tarde o temprano saldrá una actualización de tal o cual .dll o incluso de hardware que echará por tierra el buen funcionamiento de todo componente.

Y las disculpas anticipadas, era por este comentario:
"Entonces, no usarás la JVCL ¿verdad? siguiendo tu línea ¡¡es descabellado usar la JVCL!! ¡¡ está plagado de todo's y not implemented yet!!".

En fin, no puedo aportar nada de valor al hilo y no quiero desvirtuar más de lo necesario, así que con el permiso de venia, me retiro.

... bueno... quizás sí... Sick Boy, si quieres un TMDOAutoDataset, es decir, un componente que se crea en ejecución y que dando la sql de selección genera automáticamente las demás sqls de inserción, borrado y actualización, dilo y subo el archivo.
Creo que ya me disculpe, o no.... Bueno, no quiero empezar una polemica sobre lo bonitos o mejor comentados que estan los codigos. La gente de MDO no creo los componentes desde cero, asi que no se de quien es el merito.

Si, uso JVCL, y si, he visto las lindezas que tiene y he aprendido a vivir con ellas.
Que yo no digo que sean una mierda de componentes, es solo que esto me parece "una chapuza" por el problema concreto que estoy teniendo.
Ademas, que existan componentes peores o mejores no es excusa.

Como dice Al, mejoraron la solucion de los IBX, un punto a su favor, y si bien yo anteriormente calificaria a los componentes como "EXCELENTES", ahora entenderas que no pueden tener la misma nota, y no sabria que nota ponerles, quizas utilizarlos sea un poco arriesgado.

Cita:
falso. El generador de numeros random de delphi es de pseudoaleatorios. Si se tiene algun randomize o randseed fijo en la aplicación, justo antes de crear un MDOQuery dinamicamente, se le repetira el numero en la misma iteración.
Si, tengo un randomize, luego repaso lo que sucede con él.

Cita:
Sobre el hecho de que solo ocurra en una maquina, y esta sea la del cliente, es lo que mas me intriga. Pense si el nombre de la tabla pueda tener algo que ver, o incluso la tabla de codigos
Esto es con diferencia lo más extraño que me ha pasado nunca, pero es asi, yo tampoco me lo creia hasta que lo vi con mis propios ojos.
Mismo nombre de tabla, misma tabla de codigos, todo igual.
Responder Con Cita
  #3  
Antiguo 14-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
A sugerencia de Coso, le añadi un timetostr(now) al nombre del cursor. Le añadi tambien un numero aleatorio de 1 digito y ya no aparece el error en mi equipo, el lunes lo probaré en el cliente, pero con la hora y 8 digitos aleatorios.

Esto deberia ser suficiente para que no se repitan.
Vale, ya lo se, cada 24 horas.... el tiempo comienza a repetirse, pero los 8 digitos aleatorios deberian ser suficientes.

He pensado en añadirele tambien el dia del mes, ¿que pensais vosotros??

PD: Dejar un espacio en blanco en el nombre del cursor lo trunca. Por ejemplo "cursor, portate bien" quedaria como "cursor,"
Responder Con Cita
  #4  
Antiguo 14-12-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Sobre el 'name', creo que andas equivocado: después del create es cuando se le asignan los valores del inspector de propiedades al objeto, y seria muy raro que no se asignara nombre si haces, por ejemplo

Código Delphi [-]
var
  m : TMDOQuery;
begin
  m := TMDOQuery.Create(self);
  m.Name := 'test';
  ShowMessage(m.Name);
end;

si esto te muestra una cadena vacia, hay un problema gordo
Sobre lo del tiempo, usaria todas las cifras de fecha y hora : nunca son iguales

Código Delphi [-]
//fecha : 21/03/2003, hora : 13:09:23

s := Stringreplace(DateToStr(date) + TimeToStr(now),'/','',[rfReplaceAll]);
s := StringReplace(s,':','',[rfReplaceAll]);

s tendria que ser '21032003130923'

Cita:
Si se tiene algun randomize o randseed fijo en la aplicación...
corrijiendome, si se tiene un randseed. En teoria el randomize tendria que generarte cadenas nuevas

Última edición por coso fecha: 14-12-2008 a las 16:31:05.
Responder Con Cita
  #5  
Antiguo 14-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, me ha sido de mucha ayuda.

Si, tengo un randseed, y es lo que me anda provocando el problema, lo tengo bastante claro.

Tengo un timer que encripta y envia una información cada cierto tiempo.
Es algo opcional, parece que solo este cliente lo tiene activado.
Al encriptar utilizo una rutina que inicializa el randseed.
Cuando hicimos las pruebas, no esperamos el tiempo suficiente para que los cursores empezaran a repetirse, asi que todo parecia estar correctamente.

Ya sabemos las "determinadas circunstancias" en las que los MDO daran problemas. Es mas, creo que los IBX tambien tendran el mismo problema.

La solucion pasa por eliminar los cursores aleatorios y convertirlos en unicos.

Lo de que la fecha y la hora no se repiten es relativo. Si el cliente modifica la fecha y hora del windows hacia atras comenzaria la pesadilla. Tambien con los cambios de horario de verano/invierno.

Lo ideal seria conseguir numeros unicos, quizas utilice GUI, si es que no se ve afectado por el randseed

Voy a hacer las pruebas activando la opcion que reinicia la semilla y os comento.
Responder Con Cita
  #6  
Antiguo 14-12-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Yo no gastaría más tiempo en el randseed, está claro que al ejecutarlo reinicializa la semilla y es cuando empiezan los problemas.

¿puedes crear un simple número Int64 e ir incrementándolo cada vez que se crea un nuevo cursor? Obviamente lo pasas a string y ya tienes números bastante grandes. Incluso puedes guardarlo en un archivo .ini y continuar con él hasta cierto número predeterminado, después de eso lo reinicias:

Los GUID son creados por Microsoft y por ello no sabemos cómo están hechos, (al menos yo).

Ya puesto, puedes mezclar y el formato de fecha y hora, incluyendo milisegundos con un Int64:
Código Delphi [-]
//   Min int64 value = -9223372036854775808
//   Max int64 value = 9223372036854775807

miLong := (miLong  + 1 )
if miLong > high(int64) -1 then
  miLong := low(int64);

query.name = formatDatetime('yyyymmddhhnnsszzz', now) + inttostr(miLong);

El problema según creo entender son esos cursores que acceden a las tablas de sistema ¿no?

Suerte
__________________
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: 14-12-2008 a las 16:53:19.
Responder Con Cita
  #7  
Antiguo 14-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
Lo que propone Lepe estaria bien, pero resulta que el name nunca llega hasta el codigo donde se crea el cursor.

He puesto un comprobante para que salte si al crear el cursor name<>'', y ninguno de los cursores recibe valor en name. Ni los puestos en tiempo de diseño, ni los creados en ejecucion (añadiendo query.name explicitamente), tanto querys como datasets. Creo que Al Gonzaléz me advirtió de que esto pasaria, aunque no se como lograr que funcione.

Yo pude reproducir el error con cursores de un solo digito, y las sentencias más afectadas eran las de tablas de sistema, ya que no se en que transacción estan, ni cada cuanto tiempo se abren y cierran.

Con las sentencias SQL que creo yo acostumbro a abrir la transaccion, ejecutar el SQL y cerrarla. Como los cursores creo que tienen ambito a nivel de transacion, no es facil que coincidan dos cursores abiertos con el mismo nombre.
Responder Con Cita
  #8  
Antiguo 14-12-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Creo que no estoy entendiendo algo.... no puede ser tan fácil, a ver, yo he hecho lo siguiente:
- en mdosql.pas he añadido una nueva propiedad pública al TMDOSQL:
Código Delphi [-]

    property UniqueRelationName: string read GetUniqueRelationName;
    property UniqueCursorName:string read FCursor write FCursor; <<<< esta es la linea añadida
  published
    property Database: TMDODatabase read GetDatabase write SetDatabase;

y ahora en el Prepare:
Código Delphi [-]
procedure TMDOSQL.Prepare;
var
  stmt_len: Integer;
  res_buffer: array[0..7] of Char;
  type_item: Char;
begin
//  if FCursor = '' then
//    FCursor := Name + RandomString(8);
  if FCursor = EmptyStr then
    raise Exception.Create('Not asigned UniqueCursorName property !');

FCursor es una variable protegida, ni propiedad ni nada, es una simple y mortar variable, pues la reuso y me quedo tan pancho.

- Guardo y cierro todo.
- Abro el paquete de los mdo que está en la carpeta "source" con nombre mdo_dX, pulso F12 para que aparezca la ventanita de compilación y pulso el botón compilar.
- Listo, Ahora ya tengo una propiedad en el TMDOSQL que se llama "UniqueCursorName:string" que desde mi programa principal puedo asignar su valor.

En el caso de que se te olvide asignar esa propiedad, en ejecución obtendrás una excepción muy bonita. Además no creo que se te olvide nunca...

¿qué es lo que me estoy perdiendo?

PD: Si ahora me alguien con aquello de que esto es una chapuza más grande, pues que lo pinte de amarillito y con flores

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: 14-12-2008 a las 22:46:56.
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 07:49:35.


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