Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Mensaje de error extraño (https://www.clubdelphi.com/foros/showthread.php?t=62241)

Sick boy 12-12-2008 12:23:27

Mensaje de error extraño
 
Hola,

Hace 3 semanas que me estoy volviendo loco con un error en una base de datos Firebird 2.1. Uso Delphy 7 y MDO (Mercury Database Objects)

El error es:
Dynamic SQL ErrorSQL error code= -502 Invalid cursor declaration. Statement alreaady has a cursor XXXXXXX

Entiendo lo que dice el error, los componentes MDO me indican que se esta intentando redeclarar un cursor.

El cursor XXXXXXX esta creado hasta que cierras el programa, de modo que una vez que comienza el error, el numero XXXXXXX aparece varias veces en el error, aunque segun lo que hagas, pueden salir numeros diferentes. Lo que es seguro es que una vez da el error en un cursor, este no se libera, y continua dando errores.

Lo raro es que es:
1.- ALEATORIO. El error comienza a salir aproximadamente 45 minutos despues de comenzar a trabajar con la BBDD. No hay una sentencia en concreto que falla, puede fallar en cualquier sitio.
2.- Solo pasa en 1 base de datos, otras bases de datos iguales funcionan sin problemas.
3.- El programa que accede a la base de datos es el mismo, y llevaba 6 meses funcionando sin problemas.
4.- Si restauro la copia de seguridad en otro equipo, no consigo que aparezca el dichoso error.

El problema surgió del siguiente modo:
1.- Realicé un BackUp de la BBDD, version 2.0
2.- Desinstale Firebird 2.0 e instale 2.1 SuperServer
3.- Restauré la copia de seguridad.
4.- Arranque el programa e inicialmente estaba todo bien, ningun error en todo el proceso.
5.- Me conecté con el servidor via TCP para comprobar la conexion, y todo correcto.

Al dia siguiente, comenzó a salir este error.

He buscado y rebuscado, o no hay nada sobre el error, o son post muy antiguos.

¿Ha nadie le ha pasado????

He probado de todo (uno a uno y en este orden):
** backup y restore (ningun mensaje de error)
** Modifique el firebird.config, aumentando cached database pages a 8192
** gfix (todas las opciones que se ocurrieron, ningun error)
** Volcado de datos manual a una BBDD vacia y nueva (hice una aplicacion que lee los datos y los inserta mediante un query uno a uno, haciendo un commit cada X registros, luego ajusta los generadores y deja la BBDD clonada)

Como veis, no tengo ni idea de por donde atacar el problema

AYUDAAAAAAAAAAAAA, por favorrrrrrrrrrrrr

Quizas este equivocado, pero creo que el problema no esta en mi codigo, entiendo que de ser asi tendría problemas con todas las bases de datos, no solo con esta en concreto.

No se si via codigo hay alguna forma de "bordear" la excepcion, intentando que cuando salte el problema, los MDO utilicen el cursor existente, en lugar de intentar crearlo de nuevo.

Por otro lado, la numeracion de los cursores no es aleatoria????
Si es aleatoria, que mala suerte que mi programa intente declarar aleatoriamente siempre el mismo cursor, no se, es muy raro.

En algun sitio leí que era mejor cambiar los Tquery por TSQL, supongo que no hay mucha diferencia. Que pensais???

Por favor, ayuda, estoy desesperado.

coso 12-12-2008 12:56:05

Hola, te doy algunas pistas a ver si por alla lo solucionas.

- usa refresh despues de las operaciones con la base de datos, o bien TQuery.Autorefresh a true (o equivalente)
- TQuery.UpdateMode a upWhereChanged (o equivalente con tus componentes)

o bien cambia a ADO: con los TQuery usuales me empezaron a salir estos errores por no usar refresh ni updates. Cambie a ADO, y desaparecieron todos :D. Saludos.

Ñuño Martínez 12-12-2008 13:13:12

No repitas los mensajes :mad:

Sick boy 12-12-2008 13:30:23

gracias, ahora empiezo a probar lo que me comentas, aunque tardaré casi un dia en saber si funciona.

Cita:

usa refresh despues de las operaciones con la base de datos, o bien TQuery.Autorefresh a true (o equivalente)
Supongo que te refieres a despues de ejecutar una sentencia de INSERCION/ACTUALIZACION, o tambien de un simple SELECT????

Mas informacion sobre como trabajo:
** Para datos que sean actualizables utilizo TDataSet, en muy contadas ocasiones uso TUpdateSQL para actualizar grids con Tquerys
** ForcedRefresh esta a FALSE en Datasets y Querys. Es el valor por defecto, y asi me funcionaba sin problemas.

Cita:

o bien cambia a ADO: con los TQuery usuales me empezaron a salir estos errores por no usar refresh ni updates. Cambie a ADO, y desaparecieron todos .
Hombre, un poco drastico, pero recojo tu sugerencia y la tendré en mente.
¿Alguno más piensa que debo sustituir los MDO???


Es más facil que me equivoque yo al programar, supongo que no es un bug de Firebird, pero, ¿no podria ser un error del archivo de la base de datos?? ¿o un problema de motor mal instalado?? ¿o un conflicto con algo instalado en su windows??

Sick boy 12-12-2008 13:34:43

Cita:

No repitas los mensajes
Gracias por el consejo, no lo repeti por gusto, el señor moderador puede borrar el que sobra.

Resulta que despues de enviar el post, el navegador no me devolvio la pagina del foro, sino que me envió para descargar un archivo .php de vuestro servidor :eek::eek::eek:

Pensaba que no se habia enviado nada, asi que di para atras y volvi a enviar, esta vez si que me mostró lo esperado.

Cuando me di cuenta de que habia 2 post, intenté borrar uno, pero no tengo permisos.

Te pido disculpas si te ha molestado.

Si tienes alguna sugerencia más que añadir..... a ser posible sobre mi problema..... gracias

coso 12-12-2008 15:02:17

Cita:

...o tambien de un simple SELECT
si, tambien de un simple select. Ya te digo que al final lo cambie todo a ADO porque los problemas de recolocación del cursor saltaban cuando y como querian :confused::confused::confused: Debe haber una manera correcta de solucionarlos. Yo la desconozco :( aunque ya te digo que creo q va por el tema de update. Saludos.

Sick boy 12-12-2008 15:31:05

gracias coso

Cita:

si, tambien de un simple select.
uffff, vaya desastre.... alguno más puede confirmar esto????

Cita:

Ya te digo que al final lo cambie todo a ADO porque los problemas de recolocación del cursor saltaban cuando y como querian
ADO es igual de rapido??

Hay que cambiar muchas cosas para pasar de MDO a ADO?? encontraste problemas durante el cambio?? las transacciones se gestionan igual??

¿por que surgen solo en uno de los clientes?? ¿¿ por que a mi no me sale el problema al restaurar la copia de seguridad??

Estoy totalmente perdido :confused::confused:

Al González 12-12-2008 19:51:53

:) ¡Hola!

A raíz de este mensaje me entero que existe, al menos en Firebird e InterBase, una sentencia SQL llamada Declare Cursor (me pregunto si tendrá que ver con las recientemente mencionadas tablas temporales).

Según se desprende del mensaje de error, es como si se estuviera ejecutando dos veces un mismo Declare Cursor sin un Close entre uno y otro:

Código SQL [-]
Declare MiCursor Cursor For Select...
...
Close MiCursor  -- (como si esta sentencia SQL no fuese ejecutada)
...
Declare MiCursor Cursor For Select...

Algo que puedes hacer es buscar ese tipo de sentencias SQL en los fuentes de MDO, y seguirles la pista con el depurador. A ver cuándo se lanza el Declare y cuando se lanza el Close. No conozco los MDO, pero, considerando que son relativamente populares, quizá hagas algo mal desde tu programa, omitiéndose alguno de esos cierres de cursor.

Claro, esto mismo puede estar ocurriendo dentro de los disparadores y procedimientos almacenados, si es que dentro de ellos hay sentencias para creación, manejo y cierre de cursores.

En conclusión, es probable que se esté omitiendo uno de esos Close por algún descuido en el código de tu programa o en el código de los disparadores y SPs. La razón por la que esto ocurre tan azarosamente puede residir en alguna condición que, por no cumplirse, impida entrar al bloque de código o llamar a la rutina donde se ejecuta el cierre, o por algún error (excepción) previo no bien manejado que interrumpa la ejecución normal del programa.

Espero logres solucionarlo, apóyate en el depurador de oro de Delphi y échale un vistazo a las rutinas internas de la base de datos.

No dejes de comentarnos.

Al González. :)

Ñuño Martínez 12-12-2008 22:36:30

Cita:

Empezado por Sick boy (Mensaje 330655)
Gracias por el consejo, no lo repeti por gusto, el señor moderador puede borrar el que sobra.

Resulta que despues de enviar el post, el navegador no me devolvio la pagina del foro, sino que me envió para descargar un archivo .php de vuestro servidor :eek::eek::eek: (...)

Ah, bueno, si fue eso pues nada. Lamento la intromisión. Es que hay gente que repite los mensajes cuando se tarda en contestar.

Respecto al tema, poco más que nuestros compañeros puedo decir. En Delphi casi siempre he utilizado el método clásico del TDataTable. Sí utilicé ADO una temporada y lo encontré algo confuso, no sabría decirte. Yo creo que deberías probarlo para que puedas comprobar por ti mismo cuál te es más cómodo y cuál es más adecuado a tu proyecto.

Sick boy 12-12-2008 22:58:08

Hola AI, gracias por tu aporte.

Cita:

Algo que puedes hacer es buscar ese tipo de sentencias SQL en los fuentes de MDO, y seguirles la pista con el depurador. A ver cuándo se lanza el Declare y cuando se lanza el Close. No conozco los MDO, pero, considerando que son relativamente populares, quizá hagas algo mal desde tu programa, omitiéndose alguno de esos cierres de cursor.
Tengo localizados todos los puntos por donde pasa el programa cuando se produce el error.
Es totalmente aleatorio, pero si repaso, veo que las funciones que más se usan son las que más errores provocan.

Pongo el trazado por si veis mas que yo :eek::eek:
El numero (1463 TMDOTransaction.Call) indica la linea donde se produce el error. Ahora mismo no tengo a mano el contenido de esa linea, pero lo pondré mañana.
Código SQL [-]
exception class   : EMDOFirebirdError

exception message : Dynamic SQL ErrorSQL error code = -502Invalid cursor declaration
Statement already has a cursor 11249867 assigned.



main thread ($724):

005048cb programa.exe MDO               390 MDODataBaseError

00511d5f programa.exe MDODatabase      1463 TMDOTransaction.Call

0050bb4e programa.exe MDOSQL           1932 TMDOSQL.Call

0050bdcc programa.exe MDOSQL           2014 TMDOSQL.ExecQuery

00518061 programa.exe MDOCustomDataSet 2335 Add_Node

00518161 programa.exe MDOCustomDataSet 2359 Has_COMPUTED_BLR

005186f2 programa.exe MDOCustomDataSet 2531 TMDOCustomDataSet.InternalInitFieldDefs

005195c0 programa.exe MDOCustomDataSet 2890 TMDOCustomDataSet.InternalPrepare

0051c741 programa.exe MDOQuery          261 TMDOQuery.PrepareSQL

0051cef2 programa.exe MDOQuery          452 TMDOQuery.SetPrepared

0051c6f0 programa.exe MDOQuery          241 TMDOQuery.InternalOpen

00500021 programa.exe DB                    TDataSet.DoInternalOpen

005000da programa.exe DB                    TDataSet.OpenCursor

004fff95 programa.exe DB                    TDataSet.SetActive

004ffde0 programa.exe DB                    TDataSet.Open

008c2b63 programa.exe Unit3             860 TForm3.select_clientes

008c2960 programa.exe Unit3             816 TForm3.Timer1Timer



********************************************************************************



exception class   : EMDOFirebirdError

exception message : Dynamic SQL ErrorSQL error code = -502Invalid cursor declaration
Statement already has a cursor 19377446 assigned.



main thread ($724):

005048cb programa.exe MDO               390 MDODataBaseError

00511d5f programa.exe MDODatabase      1463 TMDOTransaction.Call

0050bb4e programa.exe MDOSQL           1932 TMDOSQL.Call

0050bdcc programa.exe MDOSQL           2014 TMDOSQL.ExecQuery

00518061 programa.exe MDOCustomDataSet 2335 Add_Node

00518161 programa.exe MDOCustomDataSet 2359 Has_COMPUTED_BLR

005186f2 programa.exe MDOCustomDataSet 2531 TMDOCustomDataSet.InternalInitFieldDefs

005195c0 programa.exe MDOCustomDataSet 2890 TMDOCustomDataSet.InternalPrepare

0051c741 programa.exe MDOQuery          261 TMDOQuery.PrepareSQL

0051cef2 programa.exe MDOQuery          452 TMDOQuery.SetPrepared

0051c6f0 programa.exe MDOQuery          241 TMDOQuery.InternalOpen

00500021 programa.exe DB                    TDataSet.DoInternalOpen

005000da programa.exe DB                    TDataSet.OpenCursor

004fff95 programa.exe DB                    TDataSet.SetActive

004ffde0 programa.exe DB                    TDataSet.Open

008f1386 programa.exe Unit2            7984 TForm2.buscar_cliente



********************************************************************************



exception class   : EMDOFirebirdError

exception message : Dynamic SQL ErrorSQL error code = -502Invalid cursor declaration
Statement already has a cursor 19377446 assigned.



main thread ($724):

005048cb programa.exe MDO               390 MDODataBaseError

00511d5f programa.exe MDODatabase      1463 TMDOTransaction.Call

0050bb4e programa.exe MDOSQL           1932 TMDOSQL.Call

0050bdcc programa.exe MDOSQL           2014 TMDOSQL.ExecQuery

00518e37 programa.exe MDOCustomDataSet 2684 TMDOCustomDataSet.InternalOpen

0051c713 programa.exe MDOQuery          245 TMDOQuery.InternalOpen

00500021 programa.exe DB                    TDataSet.DoInternalOpen

005000da programa.exe DB                    TDataSet.OpenCursor

004fff95 programa.exe DB                    TDataSet.SetActive

004ffde0 programa.exe DB                    TDataSet.Open

008e28d8 programa.exe Unit2            4950 TForm2.familias





********************************************************************************



exception class   : EMDOFirebirdError

exception message : Dynamic SQL ErrorSQL error code = -502Invalid cursor declaration
Statement already has a cursor 17264469 assigned.



main thread ($ffc):

005048cb programa.exe MDO               390 MDODataBaseError

00511d5f programa.exe MDODatabase      1463 TMDOTransaction.Call

0050bb4e programa.exe MDOSQL           1932 TMDOSQL.Call

0050bdcc programa.exe MDOSQL           2014 TMDOSQL.ExecQuery

00518e37 programa.exe MDOCustomDataSet 2684 TMDOCustomDataSet.InternalOpen

0051c713 programa.exe MDOQuery          245 TMDOQuery.InternalOpen

00500021 programa.exe DB                    TDataSet.DoInternalOpen

005000da programa.exe DB                    TDataSet.OpenCursor

004fff95 programa.exe DB                    TDataSet.SetActive

004ffde0 programa.exe DB                    TDataSet.Open

007c7fa4 programa.exe Unit14            199 TForm14.FormShow



********************************************************************************



exception class   : EMDOFirebirdError

exception message : Dynamic SQL ErrorSQL error code = -502Invalid cursor declaration
Statement already has a cursor 18422997 assigned.



main thread ($ffc):

005048cb programa.exe MDO               390 MDODataBaseError

00511d5f programa.exe MDODatabase      1463 TMDOTransaction.Call

0050bb4e programa.exe MDOSQL           1932 TMDOSQL.Call

0050bdcc programa.exe MDOSQL           2014 TMDOSQL.ExecQuery

00518061 programa.exe MDOCustomDataSet 2335 Add_Node

00518161 programa.exe MDOCustomDataSet 2359 Has_COMPUTED_BLR

005186f2 programa.exe MDOCustomDataSet 2531 TMDOCustomDataSet.InternalInitFieldDefs

005195c0 programa.exe MDOCustomDataSet 2890 TMDOCustomDataSet.InternalPrepare

0051c741 programa.exe MDOQuery          261 TMDOQuery.PrepareSQL

0051cef2 programa.exe MDOQuery          452 TMDOQuery.SetPrepared

0051c6f0 programa.exe MDOQuery          241 TMDOQuery.InternalOpen

00500021 programa.exe DB                    TDataSet.DoInternalOpen

005000da programa.exe DB                    TDataSet.OpenCursor

004fff95 programa.exe DB                    TDataSet.SetActive

004ffde0 programa.exe DB                    TDataSet.Open

008c210d programa.exe Unit3             689 TForm3.Edit16Change



*************************************************************************************

Tengo el codigo fuente de los MDO, con la linea a la que hace referencia. Si puede servir para algo lo posteo.

El problema al tratar de depurar, es que esos mismos procedimientos funcionan bien en otros equipos, incluso en el equipo ahora afectado llevaba 6 meses funcionando sin ningun problema.

Incluso con la base de datos que da este error, estos procedimientos funcionan bien la mayoria de las veces, pero en ocasiones (cada hora de trabajo o más) empieza a dar fallos.

Algunos de los forms del informe nunca se destruyen, otros se crean en ejecucion. Algunas de las querys que han dado error funcionan sin problemas desde hace años.

No es que no pueda haber un error en mi codigo, solo que es muy raro, y parece haberse propagado por todas partes.

Los MDO llevo 2 años usandolos sin problemas hasta ahora.

Lepe 13-12-2008 09:01:26

Ojalá me equivoque pero... que yo sepa MDO lleva más de 1 año o 2 sin actualizarse, así que podría tratarse de no ser compatible con Firebird 2.

En un programa de prueba, con Firebird 1.5 funcionaba de lujo, con Firebird 2, me empezaba a dar errores de la API del motor :(.

Yo elegí MDO porque estaban más avanzados que ZEOS en aquel momento, pero ahora ZEOS sigue actualizándose mientras que MDO se quedó estancado.

Lamento dar este punto de vista pesimista... pero en fin, es mi opinión.

Saludos y suerte

Sick boy 13-12-2008 12:07:11

Hola Lepe,

Si, es cierto que MDO lleva tiempo parado, bastante tiempo, y no parece que vaya a arrancar de nuevo.
Acabo de revisar su web, parece que yo empece a trabajar con ellos justo cuando dejaron de actualizarlos :(

Hasta ahora, me ha funcionado desde la 1.5 hasta la 2.1 sin ningun problema (bueno, salvo esto).

Tras documentarme un poco más sobre ADO (solo habia hecho algo hace años para acces) no creo que sea la opcion que escoja si cambio de componentes.

ZEOS son muy usados, y como dices, siguen actualizandose.
Si cambiase los MDO probablemente fuera por los ZEOS.

Una cosa de los ZEOS, por lo que he visto, no tienen componente para las transacciones, ni un dataset como el de MDO (aunque se puede suplir con un query y un updatequery).
Las transacciones las gestiona automatico??
Cambia mucho la forma de trabajo con ZEOS??

Voy a repasar mi codigo y estudiar un poco del codigo de los MDO y pongo lo que encuentre.

gracias por vuestra ayuda.

Sick boy 13-12-2008 14:53:35

Todo empieza aqui, este codigo se ejecuta sin problemas

Código:

procedure TMDOQuery.InternalOpen;
begin
  ActivateConnection();
  ActivateTransaction;
  QSelect.GenerateParamNames := FGenerateParamNames;
  SetPrepared(True);
  if DataSource <> nil then
    SetParamsFromCursor; 
  SetParams;
  inherited InternalOpen;
end;

Ahora intenta ejecutar el query
Código:

procedure TMDOCustomDataSet.InternalOpen;
var
  SetCursor: Boolean;

  function RecordDataLength(n: Integer): Long;
  begin
    result := SizeOf(TRecordData) + ((n - 1) * SizeOf(TFieldData));
  end;

begin
  SetCursor := (GetCurrentThreadID = MainThreadID) and (Screen.Cursor = crDefault);
  if SetCursor then
    Screen.Cursor := crHourGlass;
  try
    ActivateConnection;
    ActivateTransaction;
    if FQSelect.SQL.Text = '' then
      MDOError(mdoeEmptyQuery, [nil]);
    if not FInternalPrepared then
      InternalPrepare;
  if (FQSelect.SQLType in [SQLSelect, SQLSelectForUpdate]) then
  begin
      if DefaultFields then
        CreateFields;
      BindFields(True);
      FCurrentRecord := -1;
      FQSelect.ExecQuery;

............. hay mas codigo, pero nos interesa hasta ExecQuery ........

Ahora intenta establecer el nombre del cursor con una llamada call
Código:

procedure TMDOSQL.ExecQuery;
var
  fetch_res: ISC_STATUS;
begin
  CheckClosed;
  if not Prepared then
    Prepare;
  CheckValidStatement;
  if (FBase.Transaction.AutoCommit) and
    not (FBase.Transaction.InTransaction) then
  begin
    FBase.Transaction.StartTransaction;
  end;

  try
    case FSQLType of
      SQLSelect, SQLSelectForUpdate: begin
        Call(isc_dsql_execute2(StatusVector,
                              TRHandle,
                              @FHandle,
                              Database.SQLDialect,
                              FSQLParams.AsXSQLDA,
                              nil), True);
AQUI->> Call(
          isc_dsql_set_cursor_name(StatusVector, @FHandle, PChar(FCursor), 0), True);
        FOpen := True;
        FBOF := True;
        FEOF := False;
        FRecordCount := 0;
        if FGoToFirstRecordOnExecute then
          Next;
      end;

Fcursor debe tener la informacion que buscamos, asi que hago una busqueda en el codigo y encuentro esto en el CONSTRUCTOR de TMDOSQL:
// Removed the code FCursor set name from the TMDOSQL.Create.
// This is needed because if you create the MDOSQL dynamically, the name is
// not assigned in the create and the cursor is only based on a 'random'
// number. And, in some special situation, duplicate cursornames will appear
//FCursor := Name + RandomString(8);

buffff, atentos a esto: "And, in some special situation, duplicate cursornames will appear" !!!!!

Justo lo que me sucede ahora, ya que muchas querys las creo dinamicamente. Ya me gustaria saber cual es la "special situation" a la que se refieren....

Vale, ya tenemos localizado el problema, los creadores de MDO ya lo sabian, veamos como lo resolvieron....

Código:

procedure TMDOSQL.Prepare;
var
  stmt_len: Integer;
  res_buffer: array[0..7] of Char;
  type_item: Char;
begin
  if FCursor = '' then                        !! Parece que NO LO RESOLVIERON !!!
    FCursor := Name + RandomString(8);        !! Utilizan el randomstring(8) igual que en el codigo editado en el constructor !!
  CheckClosed;
  FBase.CheckDatabase;
  FBase.CheckTransaction;
  if FPrepared then
    exit;
  if (FSQL.Text = '') then
    MDOError(mdoeEmptyQuery, [nil]);
  if not ParamCheck then

........ continua ......

En mi caso, los cursores que dan errores solo lo forman 8 numeros, el "Name" parece no contener ningun valor.

Estas son las funciones que generan el nombre (numero) del cursor.
Código:

function RandomString(iLength: Integer): String;
begin
  result := '';
  while Length(result) < iLength do
    result := result + IntToStr(RandomInteger(0, High(Integer)));
  if Length(result) > iLength then
    result := Copy(result, 1, iLength);
end;

function RandomInteger(iLow, iHigh: Integer): Integer;
begin
  result := Trunc(Random(iHigh - iLow)) + iLow;
end;

Ahora mi duda es la siguiente, ¿Garantizan estas funciones numeros aleatorios para los cursores??

Si no son seguras, se pueden mejorar???

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.

Los componentes MDO son los que se encargan de los cursores, creacion y destruccion, ¿de que modo podriamos dejar los cursores huerfanos en memoria provocando este error???

Espero que este post ayude a alguien que se encuentre en esta misma situacion, creo que he avanzado bastante en localizar el problema, un poco más y descubriremos que sucede realmente.

Sick boy 13-12-2008 14:57:01

Cita:

Una cosa de los ZEOS, por lo que he visto, no tienen componente para las transacciones, ni un dataset como el de MDO (aunque se puede suplir con un query y un updatequery).
Las transacciones las gestiona automatico??
Cambia mucho la forma de trabajo con ZEOS??
Me contesto a mi mismo.

Las transacciones de controlan con TZconnection, que es como un TDataBase + TTransaction.

Pero, y si quiero tener más de una transaccion?? Hay que asignar un TZConnection por cada transaccion??

Por lo que he leido, las transacciones se pueden gestionar automatica o manualmente.

coso 13-12-2008 15:04:20

Código:

// Removed the code FCursor set name from the TMDOSQL.Create.
  // This is needed because if you create the MDOSQL dynamically, the name is
  // not assigned in the create and the cursor is only based on a 'random'
  // number. And, in some special situation, duplicate cursornames will appear
  //FCursor := Name + RandomString(8);

que cosa mas cutre...y lo peor de todo, lo dejan a sabiendas...
yo de ti no perderia mas el tiempo con estos componentes. Ahora bien, si aun los quieres usar, puedes probar de, en el create del componente, asignar el nombre del cursor de una manera que a ti te convenga :ej, numero de componentes MDOSQL en la aplicacion o con el GetNamePath, asignando el nombre a cada MDOSQL que crees dinamicamente, o bien haciendo overload del create con un parametro de cursor.

Sick boy 13-12-2008 16:10:33

Efectivamente, es una chapuza, si al menos hubieran dicho cuales son las condiciones especiales se podria tratar de evitarlas.

Parece que tendre que cambiar de componentes, pero mientras tanto, quisiera resolver esto y ganar un poco de tiempo.

Afortunadamente, solo un cliente tiene esas condiciones especiales.

No me atrevo a meterle mano al codigo de MDO, pero esta claro que de alguna manera debo modificar el nombre del cursor para hacerlo unico, pero no se como hacerlo.

Cita:

ej, numero de componentes MDOSQL en la aplicacion o con el GetNamePath, asignando el nombre a cada MDOSQL que crees dinamicamente, o bien haciendo overload del create con un parametro de cursor.
Entiendo lo que me dices, el numero de componentes creados dinamicamente es muy variable, no se si sera buena idea.
GetNamePath parece mejor opcion.

Esto funcionaria??:
FCursor := self.getnamepath + RandomString(8);

No es que no quiera probarlo yo mismo, es que me es muy dificil reproducir el error, en mis equipos no pasa.

El overload, pues no tengo ni idea de como quedaria, en este punto necesitaria un ejemplo.

Lepe 13-12-2008 18:56:52

Yo me reservo el derecho de criticar.

Para mí, una gente que trata directamente con la API de un SGBBDD y que dan al programador una interfaz al estilo de Interbase, ya se merecen mi respeto, si además lo hacen Open Source, un aplauso para ellos. Y ya ni hablar del elegante diseño de clases, jerarquías, calidad del código, etc.

Existen componentes de pago (nada baratos) que sólo ver el código fuente se les debería caer la cara de vergüenza, al menos ese fallo, conceptualmente, no tiene mucha importancia (para Sick boy si lo tendrá porque le está amargando la existencia :p).

La generación de números aleatorios siempre han tenido ese fallo, pueden repetirse en "determinadas circunstancias". Dicho sea de paso, si la función random hiciera su trabajo bien, los MDO no fallarían :p.

Saludos

coso 13-12-2008 19:42:15

Cita:

Esto funcionaria??:
FCursor := self.getnamepath + RandomString(8);
si esta creado dinamicamente y no has asignado un nombre anteriormente, no, pues es mas o menos lo que ya estaban haciendo ellos. Yo haria algo asi: pasar FCursor a protected o a public o bien crear una propiedad con el numero de cursor que es, y hacer algo asi:

Código Delphi [-]
NCursor := 0;
for i := Application (o parent o owner).ComponentCount - 1 do
if (Application.Components[i] is TMDOQuery) 
then NCursor := Max((Application.Components[i] as TMDOQuery).NCursor + 1,NCursor);

FCursor := inttostr(NCursor);

tambien, ahora que lo pienso, puedes capturar la excepción alla mismo:

Código Delphi [-]

Libre := false;
while not Libre then 
try
FCursor := Name + RandomString(8);
Call(isc_dsql_set_cursor_name(StatusVector, @FHandle, PChar(FCursor), 0), True)
...
Libre := true;
except
end;

Lo que me sigue intrigando personalmente es que tansolo te pase en una unica tabla. Quiza deberias mirar mas profundamente las diferencias entre el diseño de la tabla que da error y el resto. Saludos.

coso 13-12-2008 19:51:47

El overload seria algo asi:

Código Delphi [-]
protected
constructor Create(AOwner : TComponent); overload;
constructor Create(AOwner : TComponent; ncursor : string); overload;
...

etc...
Tambien puedes darle un nombre por defecto al componente cuando se crea aunque seria un poco estirar el problema

Código Delphi [-]
...
if FName = '' then 
Name := 'MDOQuery_' + FormatFloat('00000000',random(99999999));

Sick boy 13-12-2008 21:37:53

Cita:

Empezado por Lepe (Mensaje 330776)
Yo me reservo el derecho de criticar.

Para mí, una gente que trata directamente con la API de un SGBBDD y que dan al programador una interfaz al estilo de Interbase, ya se merecen mi respeto, si además lo hacen Open Source, un aplauso para ellos. Y ya ni hablar del elegante diseño de clases, jerarquías, calidad del código, etc.
Saludos

Bueno, lo de chapuza lo decia por el problemon que estoy teniendo, los componentes me han funcionado muy bien hasta ahora.
Un poco chapuza dejar el codigo editado y sin corregir, al menos sabian que podia haber un problema.

He revisado el codigo de los IBX y tienen el mismo codigo, esta vez sin editar, y no veo que tengan otro mecanismo para solucionarlo.

Sobre los numeros aleatorios, ¿Cuales seran las "determinadas circunstancias"?
No es que pase solo con una base de datos, es que pasa solo en un PC, yo sigo sin poder reproducir el error en mis ordenadores.

Voy a probar una modificacion en la creacion de los numeros aleatorios, y quizas tratar de capturar la excepcion como sugiere coso.

El lunes podre probarlo en el cliente y os comento si funciona.

Por cierto, las tablas son iguales, no hay ninguna diferencia. Incluso rellene una base de datos nueva y vacia con los datos de la que daba problemas, y sigue igual.


La franja horaria es GMT +2. Ahora son las 00:51:40.

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