Ver Mensaje Individual
  #13  
Antiguo 13-12-2008
Sick boy Sick boy is offline
Miembro
 
Registrado: may 2003
Ubicación: Cantabria
Posts: 245
Reputación: 21
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