Visual Foxpro 10 : Funcion psqlin y los bloqueos en las transacciones
Instaladores
Los instaladores se encuentran en la web del autor: Link de descargas. https://levelvfp.com.ar/
→ Descarga Gratuita FULL de screenclase, sqldata, sqldata2 y therm.
→ VFP 9 IDE ECOSYSTEM (reemplaza el CD original de VFP 9 IDE y lo potencia)
→ VFPA 10 32 Y 64 BITS
→ RUNTIMES PARA LOS CLIENTES
Link de descargas:
https://levelvfp-my.sharepoint.com/:f:/g/personal/gfvaldez_levelvfp_onmicrosoft_com/EpLRTWENSDFGq8qfHulkW4IBHHLozhzPSF7rNgHyIiArLw?e=K4bly1
Ruta Instalacion por defecto de los manuales
Cuando instalamos en nuestra pc la clase sqldata, sqldata2 se instala por defecto en la ruta:
C:\Program Files\LEVELVFP ARGENTINA\
Dentro de la ruta esta la carpeta manuales sqldata y sqldata2 , alli se se encuentra la documentacion oficial de la funcion psqlin , que se encuentra en el archivo otras funciones.rtf
En el curso CURSO 2 SQLDATA Y SQLDATA2 NIVEL INTERMEDIO AVANZADO-NUEVA FORMA DE PROGRAMAR se habla de la funcion psqlin , en el tiempo 1:04
Que es la funcion psqlin de VFP 10
Antes cuando se trabajaba con las transacciones se usaba el bloqueo por las tablas es decir se dejaba que la misma tabla se encargara del bloqueo. pero generaba un conflicto por eso se creo la funcion psqlin .
Funcion psqlin , esta funcion armara la cadena IN para usar para bloquear registros o para traer registros especificos de una tabla. en una clausula where
Esta funcion se explica a mas detalle en el CURSO 2 SQLDATA Y SQLDATA2 NIVEL INTERMEDIO AVANZADO-NUEVA FORMA DE PROGRAMAR en el tiempo 1:04:24
Que hace esta funcion
Que hace esta funcion psqlin , Cuando se trabaja en una factura se va cargando el detalle de una factura con el codigo de los productos , la funcion psqlin genera una instruccion para saber cuales son los id ingresados ,
Transaccion Consolidada , vamos a mover el stock de los productos ingresados por eso tenemos que asegurarnos que nadie modifique el stock de esos productos hasta que terminemos la venta , por eso tenemos que bloquear solo los productos que hemos ingresado para que nadie los modifique hasta que finalize la venta.
Aqui es donde entra a trabajar la funcion psqlin , No bloquea uno por uno los productos ingresados en el detalle de la factura , porque generaria una lentitud si se trabaja en forma remota , sino genera una instruccion where de todos los productos ingresados en el detalle de la factura y obtiene en una sola instruccion todos los bloqueos de los productos ingresados.
Ejemplo
select * from clientes where id in (1,6,8,9)
psqlin retorna una cadena parecida a esto id in (1,6,8,9), o codcli in ('0001','0002'), o combinado codcli in ('0001','0002') and numfac in ('00002','00003')
Formas de uso psqlin
psqlin tiene 2 formas de uso. unicamente usada para cursores obtenidos por consultag o consultah
Formas de uso 1
vin=osqldata.psqlin(_screen,"1",thisform,"clientes","uid","condicion")
→ "uid" = se debe indicar donde buscar la "condicion" en los "u" existentes, "i" los nuevos , "d" los eliminados. y se pueden conbinar "u" solo buscara en los existentes sin incluir los eliminados, "ud" buscara en los existentes incluidos los eliminados", "i" buscara en los nuevos, "ui" buscara en los existentes y los nuevos sin incluir eliminados", "uid" buscara en todos los registros la condicion indicada.
→ "condicion" = puede ser "modificados" o "todos" o "expresion logica" o "modificados:expresion logica".
- "modificados" = retornara una cadena in armada solamente con los registros modificados
- "todos" = retornara una cadena in armada con todos los registros indicados en "uid"
- "expresion logica" = ejemplo "idproduto=77"
- "modificados:expresion logica" = retornara los modificados y evaluara la expresion logica
Ejemplo Formas de uso 1
vin=osqldata.psqlin(_screen,"1",thisform,"clientes","u","modificados")
devolvera una cadena similar a esta id in (1,5,7,8) que buscara solo en los registros que ya existen sin incluir eliminados
Formas de uso 2
vin=osqldata.psqlin(_screen,"1",thisform,"clientes","uid",
"condicion","campoorigen1:campodestino1,campoorigen2:campodestino2)
Ejemplo Formas de uso 2
suponiedo que se quisiera armar una cadena IN de todos los id de productos vendidos de la tabla detalle seria asi :
vin=osqldata.psqlin(_screen,"1",thisform,"detalle","i","todos","idproducto:id")
devolvera algo parecido a esto: id in (3,89,98,36)
idproducto = es el nombre del campo en tabla detalle , y id es el nombre en la tabla productos.
Esto sera muy ultil para muchas cosas. por ejemplo ventas donde deban garantizar el stock y necesiten bloquear usando la funcion psqlbloquear. Traer un conjunto de registros necesarios, hacer todas las modificaciones en fox y grabarlos. en lugar de modificar uno por uno. esto les hara ganar mucha velocidad en entornos remotos.
Ejemplo Practico Grabar una venta
LOCAL vsigue
LOCAL osqldata2 as sqldata2 OF sqldata2.sqldata2
osqldata2=CREATEOBJECT("sqldata2.sqldata2")
osqldata2.psqlcomienzo(_screen,"1")
osqldata2.psqlcomtran(_screen,"1")
vinproductos=osqldata2.psqlin(_screen,"1",thisform,"detalle","todos",,"idproductos:id")
MESSAGEBOX(vinproductos)
osqldata2.psqlbloquear(_screen,"1","productos","nombre",vinproductos)
vselect="select * from productos where "+vinproductos
osqldata2.psqlejecutar(_screen,"1",thisform,,"consultag","productosvendidos","productos",vselect,,"id","restarkstock")
CURSORSETPROP("Buffering",3)
INDEX on id tag id
CURSORSETPROP("Buffering",5)
vpreciototal=0
vsigue=.t.
SELECT detalle
SCAN
SELECT productosvendidos
SEEK detalle.idproductos
replace stock WITH stock-detalle.cantidad
IF stock<0
vopcion=MESSAGEBOX("No alcanza el stock. del producto "+nombre+" Igual sigue.",36,"Atencion",10)
IF (vopcion=7 OR vopcion<1) AND vsigue=.t.
vsigue=.f.
ENDIF
ENDIF
SELECT detalle
vpreciototal=vpreciototal+preciototal
ENDSCAN
IF vsigue=.t.
SELECT cabecera
replace idclientes WITH thisform.oidclientes.value
replace total WITH vpreciototal
osqldata2.psqlgrabar(_screen,"1",thisform,"productosvendidos")
osqldata2.psqlgrabar(_screen,"1",thisform,"cabecera",,"detalle.idcabecera")
osqldata2.psqlgrabar(_screen,"1",thisform,"detalle")
ENDIF
osqldata2.psqlfintran(_screen,"1")
osqldata2.psqlfinal(_screen,"1")
IF vsigue=.f.
MESSAGEBOX("no se realizo la venta.",16,"Atencion")
ELSE
osqldata2.psqlreejecutar(thisform,"cabecera")
APPEND BLANK
replace id WITH osqldata2.psqlidr(thisform,"id")
thisform.ogrilla1.RecordSource=""
osqldata2.psqlreejecutar(thisform,"detalle")
thisform.ogrilla1.RecordSource="detalle"
thisform.onombreclientes.Value=""
ENDIF
thisform.Refresh()
Explicacion
→ Funcion psqlin
osqldata2.psqlcomienzo(_screen,"1")
osqldata2.psqlcomtran(_screen,"1")
vinproductos=osqldata2.psqlin(_screen,"1",thisform,"detalle","todos",,"idproductos:id")
Funcion psqlin genera una instruccion where de todos los productos ingresados en el detalle de la factura y obtiene en una sola instruccion todos los bloqueos de los productos a la vez.
→ Funcion psqlbloquear
osqldata2.psqlbloquear(_screen,"1","productos","nombre",vinproductos)
psqlbloquear bloquea la tabla productos
nombre = Se pone cualquier campo editable de la tabla productos menos el id ,
vinproductos = Ponemos el SQL que se genero con el where de la funcion psqlin, el sql que se desea bloquear.
Al cursor (alias) el buffering se pone a 3 para crear un indice (porque al crear un cursor se crean sin indice)
CURSORSETPROP("Buffering",3)
INDEX on id tag id
Luego lo ponemos a 5 porque sistema necesita modificar el cursor (alias)
CURSORSETPROP("Buffering",5)