Page 2 of 3
Re: problemas al usar seek con datos numericos
Posted: Sun Jan 08, 2012 8:56 pm
by joseluisysturiz
José Ríos wrote:Buen dia.
Siguiendo con muis pruebas en tdophin me encontre con un caso en que el metodo seek con datos numericos no encuentra numeros de mas de un digito.
Por ejemplo si tengo dados de alta los registros:
Numero Nombre
1 A
3 B
11 C
Y hago el siguiente query y despues 3 busquedas seek cobre el query
Code: Select all | Expand
DEFINE QUERY oQry "SELECT * FROM vendedores order by numero"
// y despues despues hago la siguientes busquedas:
If oQry:seek(2, 'Numero' ) > 0
msginfo('encontrado')
else
msginfo('no encontrado')
endif
If oQry:seek(1, 'Numero' ) > 0
msginfo('encontrado')
else
msginfo('no encontrado')
endif
If oQry:seek(11, 'Numero' ) > 0
msginfo('encontrado')
else
msginfo('no encontrado')
endif
En los dos primeros casos (numero =1 y numero=2 ), el resultado de la busqueda es exitoso, pero cuando numero=11 el registro no es encontrado.
Haciendo pruebas con find el resultado de la busqueda para numero=11 es correcto.
¿Esto significa que seek no debe usarse con campos numericos?.
Saludos.
Jose Rios.
Saludos, me habia pasado algo parecido, yo llenaba los datos manualmente a la tabla y a veces no los encontraba, es como si la tabla se embasura, prueba limpiar la tabla o cambiar el 1 o el 2 por el valor 11, ya que si te acepto el 1 y el 2, debe aceptarte el 11 ya que todos los valores son numericos, igualmente las busqueda las hago es con el valor en una VAR, intentalo de esta manera a ver..
nNum := 11
IF oQry:SEEK(nNum, "numero") = 0
.....
saludos...
Re: Tdolphin Ejemplo ABM.
Posted: Sun Jan 08, 2012 9:33 pm
by José Ríos
Jose luis gracias por tu respuesta.
Usando todas las variantes que me sugeriste me encontre con el mismo problema solo con valores numericos con valores tipo caracrer funciona bien, parece ser que la unica solucion es usar softseek.
Code: Select all | Expand
If oQry:seek(11, 'Numero' ,,,.t.) > 0 //softseek=.t.
msginfo('encontrado')
else
msginfo('no encontrado')
endif
Pero hay que tomar en cuenta que si se maneja softseek para una busqueda por un campo numerico nos traera el valor mas cercano que tal vez no se desea si se busca la existencia de un valor de un campo unico.
Saludos
Re: Tdolphin Ejemplo ABM.
Posted: Mon Jan 09, 2012 5:13 pm
by joseluisysturiz
Es raro eso que te sucede, yo hago busqueda con valores nuericos de hasta 10 digitos como son las numeros de cedula o algun numero que le asigno a una factura o documento, actualiza TDHOLPIN a su ultima version a ver si eso resuelve algo, pero a mi me trabaja muy bien, estamos a la orden, saludos...
Re: Tdolphin Ejemplo ABM.
Posted: Wed Jan 11, 2012 9:37 pm
by sysctrl2
perdon Jose,
la tabla debe de estar indexada por el campo numero,
sera tu caso ?
saludos..
Re: Tdolphin Ejemplo ABM.
Posted: Fri Jan 20, 2012 7:35 pm
by José Ríos
Buen dia.
Tengo una duda sobre los bloqueos de registro con tdolphin.
Tengo la tabla vendedores y quiero bloquear el registro con el campo numero=1 y hago lo siguiente:
oQry2:=oServer:Query( "SELECT GET_LOCK( 'vendedores.numero.1', 30) AS locked" )
msginfo(oQry2:locked)
El registro aparentemente se bloquea correctamente puesto que oQry2:locked me da el valor de 1. Pero si entro con otra instancia de mi aplicacion cuando tengo la primera instancia con el registro bloqueado NO me regresa el valor 0 para indicarme que el registro esta bloqueado me vuelve a dar el valor de 1.
Otra observacion: Aparentemente al hacer el bloqueo no se verifica correctamente la sintaxis del select puesto que si pongo un campo inexistente no me manda error y me vuelve a dar el valor de 1.
Por ejemplo:
oQry2:=oServer:Query( "SELECT GET_LOCK( 'vendedores.numeroY.1', 30) AS locked" )
msginfo(oQry2:locked)
Con este ultimo ejemplo me vuelve a dar el valor de 1 aunque el campo numeroY no existe.
¿Alguien tiene algun ejemplo que pudiera poner aqui de una aplicacion ABM con bloqueo de registros?
Saludos.
Re: Tdolphin Ejemplo ABM.
Posted: Fri Jan 20, 2012 8:05 pm
by Daniel Garcia-Gil
Hola
Existen funciones de bloqueo, pero a razon de consulta, no existen funciones de bloqueo de registro, solo para bloquear tablas ( LOCK TABLES/UNLOCK TABLES ), lo que se hace es simular un bloqueo
GET_LOCK( str, interval )
Intenta obtener un bloqueo con un nombre dado por la cadena str, con intervalo de espera interval en segundos. Retorna 1 si el bloqueo se obtiene con éxito, 0 si el intento ha agotado el tiempo (por ejemplo, porque otro cliente ya ha bloqueado el nombre), o NULL si ocurre un error. Si hay un bloqueo obtenido con GET_LOCK (), se libera cuando se ejecuta RELEASE_LOCK ().
Podra ejecutar una nueva GET_LOCK (), despues de liberarlo o cuando su conexión termina (ya sea normal o anormal). Los bloqueos obtenidos con GET_LOCK () no interactúan con las transacciones. Es decir, confirmar una transacción no libera los bloqueos que haya obtenido en la transacción.
Esta función se puede utilizar para implementar bloqueos de aplicaciones o simular bloqueo de registros. Los nombres se bloquean en el servidor. Si un nombre ha sido bloqueada por un cliente, GET_LOCK () bloquea cualquier petición de otro cliente para bloquear con el mismo nombre. Es recomendable para estas situaciones hacer bloqueos
dbname.strRELEASE_LOCK( str )
Libera el bloqueo asignado a la cadena str obtenida con GET_LOCK (). Retorna 1 si el bloqueo se libera, 0 si el bloqueo no fue establecido por este hilo (en cuyo caso el bloqueo no se libera), y NULL si el nombre de bloqueo no existiera.
Ejemplo
si queremos bloquear un registro en la tabla customer cun un ID = 4 podriamos bloquear la cadena 'customer.4'
usando en Dolphin
//bloquear
oQry = oServer:Query( "SELECT GET_LOCK( 'customer.4', 120 ) AS locked" )
//desbloquear
oQry = oServer:Query( "SELECT RELEASE_LOCK( 'customer.4' ) AS unlocked" )
pero se debe entender que el registro no esta bloquedao realmente, lo que esta bloquado es la cadena "customer.4", que se usa de forma nmemotecnica para "entender" el bloqueo... esa cadena nada tiene que ver con la tabla o la informacion de la misma
IS_FREE_LOCK( str )
Comprueba si el nombre de bloqueo str está libre para uso. Retorna 1 si el bloqueo está libre (nadie lo esta usando), 0 si el bloqueo está en uso, y NULL si se produce un error (como argumentos incorrectos).
IS_USED_LOCK( str )
Comprueba si el nombre de bloqueo str está en uso. Si es así, devuelve el identificador de conexión del cliente que tiene el bloqueo.De lo contrario, devuelve NULL.
tomado de:
http://tdolphin.blogspot.com/2010/07/bloquear-registros-record-lock.html
Re: Tdolphin Ejemplo ABM.
Posted: Sat Jan 21, 2012 12:57 am
by José Ríos
Daniel.
Gracias por responder.
Ya me quedo claro lo del bloqueo del string pero algo estoy haciendo mal que no funciona el bloqueo de la cadena.
Si un programa realiza el siguiente bloqueo:
Code: Select all | Expand
oQry2:=oServer:Query( "SELECT GET_LOCK( 'vendedores.numero.1', 30) AS locked" )
msginfo(oQry2:locked) //aqui me regresa 1 señal de que la cadena se bloqueo correctamente
y luego corro el programa otra vez sin cerrar la primera instancia del mismo y sin liberar la cadena bloqeada, y vuelve a hacer el mismo bloqueo a la misma cadena
Code: Select all | Expand
oQry2:=oServer:Query( "SELECT GET_LOCK( 'vendedores.numero.1', 30) AS locked" )
msginfo(oQry2:locked) //Aqui vuelve a regresar 1 siendo que el primer programa ya bloqueo la misma cadena ¿deberia de regresar 0?
Tengo entendido que el segundo programa me deberia de regresar 0 en oQry2:locked puesto que la cadena ya fue bloqueada por la primera instancia del programa.
¿Que estoy haciendo mal?.
Utilizo mysql embebido ¿sera por eso que no se bloquea la cadena?.
Saludos.
Re: Tdolphin Ejemplo ABM.
Posted: Sat Jan 21, 2012 10:06 am
by Daniel Garcia-Gil
José Ríos wrote:Utilizo mysql embebido ¿sera por eso que no se bloquea la cadena?.
El servidor Incrustado, se levanta en cada instancia de un programa y no se comparte con otro, es decir si ejecutas tu programa 5 veces seran 5 servidores incrustados y no tendran relacion uno con otro...
La conclusion es, si se bloquea pero no se comparte ese bloqueo con otras instancias
Re: Tdolphin Ejemplo ABM.
Posted: Sat Jan 21, 2012 10:09 am
by Daniel Garcia-Gil
Que pretendes hacer? que necesitas un bloqueo de registro, imagino que si mysql no lo ha implementado(sino una simulacion) no es necesario y existen tecnicas para lograr lo que pretendes... recuerda que es muy diferente la forma como trabajamos en DBF y MySql
Re: Tdolphin Ejemplo ABM.
Posted: Sat Jan 21, 2012 6:24 pm
by José Ríos
Daniel.
Gracias por responder.
Soy novato en MySQL, efectivamente deseaba bloquear o simular un bloqueo de registro en MySql, y entiendo que si MySql no lo implementa es porque no es necesario. Trate implementarlo en mi aplicacion para que cuando dos usuarios intenten modificar el mismo registro a uno de los dos se le notifique que el registro esta en uso por otro usuario; pero recordando la caractristica del SQL que bloquea automaticamente la tabla cuando se actualiza en el servidor, no es necesario el bloqueo del registro.
Usando dbf nos veiamos forzados a usar bloqueos de registro para que no nos aparezca un runtime error al actualizar archivos compartidos puesto que los dbf no se bloquean en forma automatica al escribir sobre ellos. En MySql el bloqueo de la tabla es automatico (configurando adecuadamente).
Despues de tantos años de trabajar con dbf al empezar a trabajar con mysql lo queremos hacer muy parecido a al manejo de las viejas bases de datos.
Seria interesante que las personas que ya tienen mas tiempo en el manejo de mysql y tdolphin compartieran sus experiencias y pusieran algunos ejemplos sencillos de programas de ABM (altas, bajas y modificaciones), para que los que somos novatos nos retroalimentaramos.
Me gustaria tambien saber si nunca debemos usar la simulacion de bloqueo de registro con MySql o bien si en alguna circunstancia seria conveniente manejarlos. Compartan su experiencia, please.
Un abrazo
Jose Rios
Re: Tdolphin Ejemplo ABM.
Posted: Sun Jan 22, 2012 10:22 am
by Daniel Garcia-Gil
Hola
Si tienes una base de datos que es accedida simultaneamente por otros usuarios, entonces te recomiendo que pases a un servidor remoto (llamese remoto que puede servir dentro de un ared local) y dejes el servidor incrustado
Re: Tdolphin Ejemplo ABM.
Posted: Sun Jan 22, 2012 5:14 pm
by José Ríos
Daniel.
Gracias por responder, mi error era usar un servidor incrustado para hacer pruebas como si el sistema estuviera en red.
Fue interesante tocar este tema para que las personas que recien empiezan a usar MySql vean las diferencias entre usar un servidor incrustado y un servidor no incrustado.
Continuare con mis pruebas sin usar servidor incrustado.
Saludos.
Jose Rios.
Re: Tdolphin Ejemplo ABM.
Posted: Sun Jan 22, 2012 5:19 pm
by nnicanor
Hola,
ya tuve la experiencia y como no estamos acostumbrados a manejar los campos autoincrementales entonces en cualquier momento se nos va a presentar duplicidad en los códigos esta es una funciones derivadas que uso espero que les sirva
Code: Select all | Expand
#include "hbclass.ch"
#include "common.ch"
#include "dbstruct.ch"
#include "tdolphin.ch"
#include "dolerr.ch"
#include "recursos.ch"
#ifndef __XHARBOUR__
#include "hbcompat.ch"
#endif
//---------------------------------------------------------------------------------------------//
CLASS SQL_QUERY FROM TDolphinQry
METHOD NEW( cQuery, oServer )
METHOD Cancel()
METHOD CLOSE() INLINE ::End()
METHOD Filter(cWhere,cOrder)
METHOD Sort(cSort)
METHOD RecordExist(aWhere)
METHOD Find_Sql(cnField, uSeek, lSoft, lRefresh)
METHOD IF_Record_Bloquear(uRecord)
METHOD Record_Bloquear(uRecord)
METHOD Record_Desbloquear(uRecord)
METHOD Load() INLINE ::GetRow()
METHOD RecordCount() INLINE ::RecCount()
ENDCLASS
//---------------------------------------------------------------------------------------------//
METHOD NEW( cQuery, oServer ) CLASS SQL_QUERY
Super:New( cQuery, oServer )
Return Self
//---------------------------------------------------------------------------------------------//
METHOD Cancel() CLASS SQL_QUERY
If ::lAppend = .T.
::lAppend = .F.
Endif
Return NIL
//---------------------------------------------------------------------------------------------//
METHOD Filter(cWhere,cOrder) CLASS SQL_QUERY
Local oQuery
Local nTotal := 0
Local cCont :="Select Count(*) From "+::aTables[ 1 ] + " WHERE " + cWhere
Local lReturn :=.F.
// Primero ver si criterio de Busqueda se Cumple
oQuery := SQL_QUERY():New(cCont,::oServer )
nTotal = oQuery:FieldGet( 1 )
IF nTotal > 0
lReturn := .T.
::cWhere := cWhere
::cOrder := cOrder
::Refresh()
Endif
oQuery:End()
Return(lReturn)
//---------------------------------------------------------------------------------------------//
METHOD Sort(cSort) CLASS SQL_QUERY
::Setorder(cSort)
Return NIL
//---------------------------------------------------------------------------------------------//
METHOD RecordExist(aWhere) CLASS SQL_QUERY
Local oQuery
Local lreturn :=.F.
Local nCount :=.0
Local cWhere :=BuildSQLSt(" WHERE "+aWhere[1] + aWhere[2] + "?", aWhere[3])
Local cSelect :="Select Count(*) From "+::aTables[ 1 ] + cWhere
oQuery := SQL_QUERY():New(cSelect,::oServer )
nCount = oQuery:FieldGet( 1 )
If nCount > 0
lReturn:=.T.
Endif
oQuery:End()
Return(lreturn)
//---------------------------------------------------------------------------------------------//
METHOD Find_Sql(cnField, uSeek, lSoft, lRefresh) CLASS SQL_QUERY
Local lReturn :=.F.
DEFAULT lSoft TO .T.
DEFAULT lRefresh TO .T.
IF ::Seek(uSeek, cnField, , ,lsoft,lRefresh) > 0
lReturn :=.T.
Endif
RETURN (lReturn)
//---------------------------------------------------------------------------------------------//
METHOD IF_Record_Bloquear(uRecord) CLASS SQL_QUERY
Local cRecord :=IF(Valtype(uRecord)="N",Rtrim(Str(uRecord)),uRecord)
Local cLockRecord :=::aTables[ 1 ]+cRecord
Local If_lock :="SELECT IS_FREE_LOCK('" + cLockRecord + "')"
Local llock :=.F.
Local nCount :=0
Local oQuery
??? cLockRecord
oQuery := SQL_QUERY():New(If_lock,::oServer )
nCount := oQuery:FieldGet( 1 )
If nCount = 1 /// 0 - esta Bloqueado Bloqueo 1 - esta Libre
llock :=.T.
Endif
oQuery:End()
??? llock
Return( llock )
//---------------------------------------------------------------------------------------------//
METHOD Record_Bloquear(uRecord) CLASS SQL_QUERY
Local cRecord :=IF(Valtype(uRecord)="N",Rtrim(Str(uRecord)),uRecord)
Local cLockRecord :=::aTables[ 1 ]+cRecord
Local IF_not_Lock :="SELECT GET_LOCK('" + cLockRecord + "',1) "
Local nCount :=0
Local oQuery, llock := .f.
oQuery := SQL_QUERY():New(IF_not_Lock,::oServer )
nCount := oQuery:FieldGet( 1 )
if ncount == 1
llock := .t.
Endif
oQuery:End()
Return llock
//---------------------------------------------------------------------------------------------//
METHOD Record_Desbloquear(uRecord) CLASS SQL_QUERY
Local cRecord :=IF(Valtype(uRecord)="N",Rtrim(Str(uRecord)),uRecord)
Local cLockRecord :=::aTables[ 1 ]+cRecord
Local If_lock :="SELECT RELEASE_LOCK('" + cLockRecord + "')"
Local nCount :=0
Local oQuery
oQuery := SQL_QUERY():New(If_lock,::oServer )
nCount := oQuery:FieldGet( 1 )
oQuery:End()
Return Nil
/// Llamados como Funciones
//---------------------------------------------------------------------------------------------//
Function QueryRow(oConect,cTabla,aField,oRecord) // Lee un registro y cierra el Query no retorna nada , manda el Obj Recordset por Referencia
Local cSelect:=BuildSQLSt("Select * From " + cTabla + " Where " + aField[1] + "=? LIMIT 1",aField[2] )
If Valtype(oRecord) == "O"
oRecord:End()
Endif
oRecord:=SQL_QUERY():New(cSelect,oConect)
oRecord:Gotop()
oRecord:End()
RETURN NIL
//---------------------------------------------------------------------------------------------//
Function Seek_Sql(oConect,cTabla,aField,oRecord) // Lee un registro y cierra la el Query Rerorna .F. o .T.
Local oTb
Local cSelect
Local lreturn:=.T.
If Valtype(oRecord) == "O"
oRecord:End()
Endif
cSelect:=BuildSQLSt( "Select * From " + cTabla + " WHERE " + aField[1] + "=? LIMIT 1",aField[2] )
oRecord:=SQL_QUERY():New(cSelect,oConect)
IF oRecord:RecCount() = 0
lreturn:=.F.
Endif
oRecord:End()
RETURN (lReturn)
//---------------------------------------------------------------------------------------------//
static FUNCTION QueryArray(oConect,cSelect )
LOCAL oTb
LOCAL aQuery
oTb:=SQL_QUERY():New(cSelect,oConect)
aQuery:=oTb:FillArray()
oTb:End()
RETURN (aQuery)
//------------------------------------------------------------------------------------------------//
Function BuildSQLSt( cWhere, cCond )
Local cSql := cWhere
strtran( cSql, "?", cCond )
Return cSql
//-------------------------------//
Function MySql_Rec_lock( id, oLock )
local forever, espera := 5
If oLock:Record_Bloquear(id) //Rlock()
Return (.T.)
Endif
Forever = (Espera = 0)
Do While (forever .Or. Espera > 0)
If oLock:Record_Bloquear(id) //Rlock()
Return (.T.)
Endif
Inkey(.5)
Espera = Espera - .5
Enddo
Return (.F.)
Re: Tdolphin Ejemplo ABM.
Posted: Sun Jan 22, 2012 5:25 pm
by nnicanor
Para simular un bloqueo hago lo siguiente no lo he pulido todavia.
Code: Select all | Expand
IF empty( oTmaniobra:maniobra )
lnuevo := .t.
oLock := Sql_Query():New( "Select * From config limit 1", oServer )
// intenta obtener el bloqueo
while ! MySql_rec_lock( oLock:id, oLock )
//msginfo("No ha podido Bloquear")
End
// msginfo("bloqueado")
oQryC := oServer:Query( "Select * From config " )
oTCfg := oQryc:GetRowObj()
??? oTCfg:maniobras
oTmaniobra:maniobra := STRZERO( oTCfg:maniobras, 10 )
oTmaniobra:user := husuario
oTmaniobra:fechareg := date()
oTmaniobra:horareg := time()
oTCfg:maniobras := oTCfg:maniobras + 1
oTCfg:Save()
oTmaniobra:lappend := .t.
// msginfo("voy a desbloquear")
oLock:Record_DesBloquear( oLock:id )
oQryc:End()
Else
oTmaniobra:lappend := .f.
Endif
cAUsuario := HUSUARIO
cAModulo := "MAN"
cAFecha := date()
cAHora := time()
cATam := 10
cAregis := oTmaniobra:maniobra
cAAccion :=""
cADetalle :=""
aTarifa := asigna_tarifa( len( ::aEqui ) )
// oTmaniobra:codtarif:=aTarifa[1,10];
oTmaniobra:estado := cEstado
IF ! lnuevo
IF !lrecal
cAAccion :="U"
cADetalle :="Actualizacion Registro maniobra"
Endif
else
if !lrecal
cAAccion :="I"
cADetalle :="Creacion de Registro maniobra"
Endif
endif
oTmaniobra:motonave := Val2Escape( oTmaniobra:motonave )
oTmaniobra:Save()
//-------------------------------//
Function MySql_Rec_lock( id, oLock )
local forever, espera := 5
If oLock:Record_Bloquear(id) //Rlock()
Return (.T.)
Endif
Forever = (Espera = 0)
Do While (forever .Or. Espera > 0)
If oLock:Record_Bloquear(id) //Rlock()
Return (.T.)
Endif
Inkey(.5)
Espera = Espera - .5
Enddo
Return (.F.)
Re: Tdolphin Ejemplo ABM.
Posted: Sun Jan 22, 2012 5:31 pm
by nnicanor
La explicacion es la siguiente, para obtener el consecutivo de maniobra ( oTmaniobra:maniobra ) debo simular un bloqueo sobre la tabla de consecutivos config (oTcfg), una vez obtenido tomo el consecutivo y lo incremento y actualizo la tabla config.
Code: Select all | Expand
oTmaniobra:maniobra := STRZERO( oTCfg:maniobras, 10 )
oTmaniobra:user := husuario
oTmaniobra:fechareg := date()
oTmaniobra:horareg := time()
oTCfg:maniobras := oTCfg:maniobras + 1
oTCfg:Save()
Espero que les sirva
Slds