/*
 * $Id$
 */


Febrero 2004
I.Q. David Arturo Macias Corona

Modificaciones a los programas de harbour\contrib\hbmysql


Programa TMySql.prg *****************************************

Clase TMySQLRow ---------------------------------------------
- DATA nueva TMySQLRow:aOriValue
  Almacena los valores originales de aRow, en la creacion del objeto TMySQLRow
  Tiene la misma funcion de TMySQLTable:aOldValue

- TMySQLRow:New()
  Asignar una copia de TMySQLRow:aRow en TMySQLRow:aOriValue

- TMySQLRow:FielPut()
  Comparar ::aRow[nNum]==NIL en vez de Empty(::aRow[nNum])
  Empty() puede ser cadena nula, valor 0, fecha nula, valor .F.

- TMySQLRow:FieldPos()
  Reduccion de codigo con misma funcionalidad para calcular nPos

- TMySQLRow:FieldLen()
  Retornar 0 en vez de cadena nula como valor de excepcion

- TMySQLRow:FieldDec()
  Retornar 0 en vez de cadena nula como valor de excepcion


Clase TMySQLQuery -------------------------------------------
- DATA nueva TMySQLQuery:lBof
  Cambio en la aplicacion de TMySQLQuery:Bof()

- DATA nueva TMySQLQuery:lEof
  Cambio en la aplicacion de TMySQLQuery:Eof()

- DATA nueva TMySQLQuery:lFieldAsData
  Se aplica por compatibilidad
  Usar nombres de los campos como elementos DATA de TMySQLQuery
  Los nombres de campos pueden coincidir con nombres de DATA en TMySQLQuery o
  TMySQLTable, lo cual puede sustituir valores y confundir las operaciones y
  el funcionamiento de las clases
  Usando TMySQLQuery:lFieldAsData := .F. se evita este conflicto

- DATA nueva TMySQLQuery:aRow
  Se usa para almacenar los valores de los campos de la fila actual, en
  sustitucion de los nombres de los campos como elementos DATA de TMySQLQuery
  Todas las operaciones sobre campos se hacen sobre esta matriz de valores

- Metodo TMySQLQuery:Bof()
  Cambio en la definicion para reproducir el comportamiento con Clipper
  BOF() verdadero se aplica cuando se intenta ir antes del primer registro logico,
  y no debe usarse para indicar que el puntero esta en el registro 1
  La definicion anterior causa que procesos como:
     WHILE ! oQuery:BOF()
       ...
       oQuery:SKIP(-1)
     ENDD
  no muestren el registro 1
  Con la nueva definicion se corrige este comportamiento

- Metodo TMySQLQuery:Eof()
  Cambio en la definicion para reproducir el comportamiento con Clipper
  EOF() verdadero se aplica cuando se intenta ir despues del ultimo registro logico,
  y no debe usarse para indicar que el puntero esta en el ultimo registro
  La definicion anterior causa que procesos como:
     WHILE ! oQuery:EOF()
       ...
       oQuery:SKIP()
     ENDD
  no muestren el ultimo registro
  Con la nueva definicion se corrige este comportamiento
  Con EOF() verdadero, el puntero de registro se ubica en LASTREC()+1

- TMySQLQuery:New()
  Aplicacion de TMySQLQuery:lBof, TMySQLQuery:lEof, TMySQLQuery:lFieldAsData,
  TMySQLQuery:aRow

- TMySQLQuery:Skip()
  Aplicacion de TMySQLQuery:lBof, TMySQLQuery:lEof para determinar movimientos
  antes del primer y despues del ultimo registros logicos
  Solamente el movimiento con SKIP puede establecer BOF() verdadero

- TMySQLQuery:Skip()
  Aplicar NIL para retorno.  DBSKIP() retorna NIL

- TMySQLQuery:GetRow()
  Aplicacion de TMySQLQuery:lBof, TMySQLQuery:lEof, TMySQLQuery:lFieldAsData,
  TMySQLQuery:aRow
  = Se usar TMySQLQuery:aRow en lugar de la variable local aRow
  = La fila por omision se aplica a TMySQLQuery:nCurRow, en lugar de mover la 
  posicion del puntero
  = Se determinan TMySQLQuery:lBof, TMySQLQuery:lEof
    TMySQLQuery:bof(): el puntero queda ubicado en fila 1
    TMySQLQuery:eof(): el puntero queda ubicado en TMySQLQuery:lastrec()+1
  = En TMySQLQuery:lastrec()+1 se usa el registro fantasma con valores nulos en cada
    tipo de campo

- TMySQLQuery:GetRow()
  = Correccion de error por tipo de dato en tipos logico y numericos
  = Supresion de mensajes con Alert() y MsgInfo() que causarian detencion en procesos
    desatendidos

- TMySQLQuery:FieldPos()
  Reduccion de codigo con misma funcionalidad para calcular nPos

- TMySQLQuery:FieldGet()
  = Se usa TMySQLQuery:aRow[nNum] en lugar de la variable DATA correspondiente al
  nombre del campo

- TMySQLQuery:FieldLen()
  Retornar 0 en vez de cadena nula como valor de excepcion

- TMySQLQuery:FieldDec()
  Retornar 0 en vez de cadena nula como valor de excepcion


Clase TMySQLTable -------------------------------------------
- Metodo TMySQLTable:Update()
  = Se agregaron los parametros:
  + lOldRecord: Usar los valores originales del registro para localizarlo
  + lRefresh: renovar la consulta al servidor MySQL para actualizar la informacion
  seleccionada para el programa Cliente

- Metodo TMySQLTable:Delete()
  = Se agregaron los parametros:
  + lOldRecord: Usar los valores originales del registro para localizarlo
  + lRefresh: renovar la consulta al servidor MySQL para actualizar la informacion
  seleccionada para el programa Cliente

- Metodo TMySQLTable:Append()
  = Se agregaron los parametros:
  + lRefresh: renovar la consulta al servidor MySQL para actualizar la informacion
  seleccionada para el programa Cliente

- Metodo TMySQLTable:GetBlankRow()
  = Se agregaron los parametros:
  + lSetValues: aplicar valores como si correspondieran a la fila actual

- Nuevo Metodo TMySQLTable:SetBlankRow()
  Aplica TMySQLTable:GetBlankRow( .T. ), con valor de lSetValues verdadero

- TMySQLTable:Skip()
  Aplicar NIL para retorno.  DBSKIP() retorna NIL

- TMySQLTable:Update(oRow, lOldRecord, lRefresh)
  = Aplicacion de TMySQLRow:aOriValue, TMySQLTable:aRow
  = Aplicacion de los parametros:
  + lOldRecord, omision .F.
    En caso de aplicar lOldRecord:
    * Usando fila actual: Utiliza los valores TMySQLQuery:aOldValue
    * Usando fila proporcionada: Utiliza los valores TMySQLRow:aOriValue
    La localizacion se basa en la coincidencia de valores de TODOS los campos, 
    usando los valores originales de la fila
    ADVERTENCIA: Si hay mas de una fila que coincida en TODOS los campos, entonces
    todas estas filas con valores comunes seran cambiadas

    Se aplico esta aproximacion para auxiliar en la localizacion de filas cuando
    no existen indices, o la llave primaria es insuficiente para determinar la 
    unicidad del registro. Sin embargo, no se puede garantizar la correspondencia
    del registro si existen varios iguales
    Es una alternativa al uso de TMySQLRow/TMySQLTable:MakePrimaryKeyWhere(), ya que
    esta ultima esta basada en campos que forman parte de una llave primaria

  + lRefresh, omision .T.
    Renueva la consulta al servidor MySQL para actualizar la informacion seleccionada
    para el programa Cliente. Es muy conveniente en caso de modificacion de informacion

  = Se mantiene el mismo apuntador de registro
  
  = Para una fila proporcionada, se actualiza TMySQLRow:aOriValue con los valores
  actuales de TMySQLRow:aRow

- TMySQLTable:Delete(oRow, lOldRecord, lRefresh)
  = Aplicacion de TMySQLRow:aOriValue, TMySQLTable:aRow
  = Aplicacion de los parametros:
  + lOldRecord, omision .F.
    En caso de aplicar lOldRecord:
    * Usando fila actual: Utiliza los valores TMySQLQuery:aOldValue
    * Usando fila proporcionada: Utiliza los valores TMySQLRow:aOriValue
    La localizacion se basa en la coincidencia de valores de TODOS los campos,
    usando los valores originales de la fila
    ADVERTENCIA: Si hay mas de una fila que coincida en TODOS los campos, entonces
    todas estas filas con valores comunes seran cambiadas

    Se aplico esta aproximacion para auxiliar en la localizacion de filas cuando
    no existen indices, o la llave primaria es insuficiente para determinar la 
    unicidad del registro. Sin embargo, no se puede garantizar la correspondencia
    del registro si existen varios iguales
    Es una alternativa al uso de TMySQLRow/TMySQLTable:MakePrimaryKeyWhere(), ya que
    esta ultima esta basada en campos que forman parte de una llave primaria

  + lRefresh, omision .T.
    Renueva la consulta al servidor MySQL para actualizar la informacion seleccionada
    para el programa Cliente. Es muy conveniente en caso de modificacion de informacion

  = Se mantiene el mismo apuntador de registro
  
  = Para una fila proporcionada, se actualiza TMySQLRow:aOriValue con los valores
  actuales de TMySQLRow:aRow


- Metodo TMySQLTable:Append(oRow, lRefresh)
  = Aplicacion de TMySQLRow:aOriValue, TMySQLTable:aRow
  = Aplicacion de los parametros:
  + lRefresh, omision .T.
    Renueva la consulta al servidor MySQL para actualizar la informacion seleccionada
    para el programa Cliente. Es muy conveniente en caso de modificacion de informacion

  = Se ubica el apuntador en TMySQLTable:lastrec()+1, antes de renovar la consulta
    Observacion: a pesar de reiteradas pruebas, no se pudo determinar en que manera
    establece el servidor MySQL la posicion de la fila insertada. Sin usar indices, en
    ocasiones la insertaba adjunta al puntero actual, en tanto que en otras ocasiones 
    la insertaba en posiciones ubicadas a 1200 o 1300 filas con respecto al puntero
    actual, o al final de la tabla (alrededor de 2880 filas)
  
  = Para una fila proporcionada, se actualiza TMySQLRow:aOriValue con los valores
  actuales de TMySQLRow:aRow
  Ademas, se inicializan TMySQLRow:aDirty y TMySQLRow:aOldValue


- TMySQLTable:GetBlankRow(lSetValues)
  = Aplicacion de los parametros:
  + lSetValues, omision .F.
  Este metodo proporciona un objeto TMySQLRow con valores por omision para el tipo de
  dato en cada campo. Como la fila generada NO es la fila actual del objeto TMySQLTable,
  entonces no deben modificarse los valores de TMySQLTable:aRow y TMySQLTable:aOldValue
  En caso de que se desee hacer esta modificacion, como si la fila vacia fuera la fila
  actual de la tabla, entonces podra aplicarse con este parametro con valor verdadero
  o con el nuevo metodo TMySQLTable:SetBlankRow()

- TMySQLTable:FielPut()
  = Comparar ::aRow[nNum]==NIL en vez de Empty(::aRow[nNum])
  Empty() puede ser cadena nula, valor 0, fecha nula, .F.
  = Se aplica TMySQLTable:aRow[nNum] para contener el valor del campo
  = De acuerdo a TMySQLTable:lFieldAsData, se actualiza el elemento DATA de TMySQLTable
  correspondiente al nombre del campo


Programa TSqlBrw.prg ************************************

- Skipper()
  Modificacion del control de movimiento para aplicar las nuevas definiciones para
  TMySQLQuery:Bof() y TMySQLQuery:Eof()

