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 13-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 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.

Última edición por Sick boy fecha: 13-12-2008 a las 11:44:42.
Responder Con Cita
  #2  
Antiguo 13-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
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.
Responder Con Cita
  #3  
Antiguo 13-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:
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.
Responder Con Cita
  #4  
Antiguo 13-12-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
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.
Responder Con Cita
  #5  
Antiguo 13-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
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.

Última edición por Sick boy fecha: 13-12-2008 a las 15:14:51.
Responder Con Cita
  #6  
Antiguo 13-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 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 ).

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 .

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #7  
Antiguo 13-12-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
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.

Última edición por coso fecha: 13-12-2008 a las 18:57:35.
Responder Con Cita
  #8  
Antiguo 13-12-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
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));
Responder Con Cita
  #9  
Antiguo 13-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:
Empezado por Lepe Ver Mensaje
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.
Responder Con Cita
  #10  
Antiguo 13-12-2008
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
...todo un misterio...¿no tendra algo que ver el nombre de la tabla?...bueno, ya nos diras. Saludos y suerte.
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 08:23:31.


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