20 de abril de 2020

TRANSFORM() un poquito mas lento que ALLTRIM(STR()), DTOC() y TTOC()

La función TRANSFORM() fue agregada a VFP hace ya algunas versiones, y es mucho mas conveniente que las equivalentes ALLTRIM(STR()), DTOC() y TTOC().

Sin embargo, es también un poquito más lenta como lo demuestra el siguiente código:

CLEAR
LOCAL lnNumber, ldDate, ltTime, lnStart, lnEnd, xx
lcString = "This is a test"
ldDate = DATE()
ltTime = DATETIME()
lnNumber = 123.456

lnStart = SECONDS()
FOR xx = 1 TO 10000
  TRANSFORM(m.lnNumber)
ENDFOR
lnEnd = SECONDS()
? "TRANSFORM(m.lnNumber)", lnEnd-lnStart

lnStart = SECONDS()
FOR xx = 1 TO 10000
  ALLTRIM(STR(m.lnNumber,7,3))
ENDFOR
lnEnd = SECONDS()
? "ALLTRIM(STR(m.lnNumber,7,3))", lnEnd-lnStart
?

lnStart = SECONDS()
FOR xx = 1 TO 10000
  TRANSFORM(m.ldDate)
ENDFOR
lnEnd = SECONDS()
? "TRANSFORM(m.ldDate)", lnEnd-lnStart

lnStart = SECONDS()
FOR xx = 1 TO 10000
  DTOC(m.ldDate)
ENDFOR
lnEnd = SECONDS()
? "DTOC(m.ldDate)", lnEnd-lnStart
?

lnStart = SECONDS()
FOR xx = 1 TO 10000
  TRANSFORM(m.ltTime)
ENDFOR
lnEnd = SECONDS()
? "TRANSFORM(m.ltTime)", lnEnd-lnStart

lnStart = SECONDS()
FOR xx = 1 TO 10000
  TTOC(m.ltTime)
ENDFOR
lnEnd = SECONDS()
? "TTOC(m.ltTime)", lnEnd-lnStart

Sin embargo, a menos que Ud. este codificando un ciclo apretado, la conveniencia de TRANSFORM() compensa lejos su pérdida de rendimiento. TRANSFORM() es solo un poquito mas lento que DTOC() y TTOC(). La diferencia de rendimiento es mayor al comparar TRANSFORM() con ALLTRIM(STR()) para convertir números a cadenas.

VFP Tips & Tricks - Drew Speedie

2 de abril de 2020

Transacciones de Usuarios en Base de Datos

Tuve la necesidad de crear una solución para ver las transacciones que podrían hacer los usuarios, debido a que trabajo con bases e datos de foxpro(DBC) , y se trataba de no meter mas código o funciones en el mismo sistema realizado, si no que el proceso fuera transparente, osea se trata de escribir un código en los procedimientos almacenados de la DBC y esto si crear prg.

1 - Abrir la base de datos a usar

Crear una tabla con con la siguiente información en la base de datos abierta

NOMBRE: HISTORIAL.DBF

Campo  Campo Nombre  Tipo       Ancho  
1      USUARIO       Caracter   20     
2      TIPO          Caracter   20     
3      FECHA         DateTime   8      
4      TABLA         Caracter   30     
5      EQUIPO        Caracter   50     
6      OBSERVA       Memo       4      

Los indices de la tabla pueden ser creados a su consideración para generar reportes o métodos de consulta propios

2 - Ir a las propiedades de la base de datos y activar la casilla de verificación "SET EVENTS ON " y después dar click a el boton "EDIT CODE", después insertar el siguiente código:

PROCEDURE Hsts(clTipo)
  LOCAL clobser
  STORE SPACE(0) TO clObser,clObservaciones,clValor,clDatos
  IF !TYPE("cp_login")="C"
    cp_login="DESCONOCIDO"
  ENDIF
  clAlias=Alias()
  If Empty("clAlias")
    Return
  Endif
  Select (clAlias)
  clRutaHistorico=ADDBS(justpath(CURSORGETPROP("Database")))+"HISTORIAL.DBF"
  USE IN (SELECT("Historial_cfg"))
  nl_error=0
  ON ERROR nl_error=1
  USE (clRutaHistorico) IN 0 SHARED AGAIN Alias Historial_cfg
  ON ERROR
  IF nl_error=0
    clObser="Campos Modificados"+CHR(13)
    FOR Ind=1 TO FCOUNT(clAlias)
      clObser=clObser+"  "+FIELD(Ind)+"=  "
      clValor=ALLTRIM(clAlias)+"."+FIELD(Ind)
      DO Case
        CASE VARTYPE(&clValor) = "N"
          clDatos=STR(&clValor,16,2)
        CASE VARTYPE(&clValor) = "C"
          clDatos=&clValor
        CASE VARTYPE(&clValor) = "D"
          clDatos=DTOC(&clValor)
        CASE VARTYPE(&clValor) = "T"
          clDatos=TTOC(&clValor)
        OTHERWISE
          clDatos=""
      ENDCASE
      clObser=clObser+clDatos+CHR(13)
    NEXT
    clObservaciones=clObser
    SELECT Historial_cfg
    APPEND BLANK
    Replace Historial_cfg.TIPO WITH clTipo,;
      Historial_cfg.FECHA WITH DATETIME(),;
      Historial_cfg.USUARIO WITH Cp_LOGIN,;
      Historial_cfg.TABLA WITH clAlias,;
      Historial_cfg.EQUIPO WITH LEFT(SYS(0),AT("#",SYS(0))-1),;
      Historial_cfg.OBSERVA WITH clObservaciones
    USE IN (SELECT("Historial_cfg"))
  ENDIF
  IF !EMPTY(clalias)
    SELECT &clAlias
  ENDIF
  ON ERROR
  RETURN
ENDPROC

3 - En la tablas importantes en donde se requiera el registro de transacciones se realizar lo siguiente modificar datos de la tabla, y ir a la pestaña "Table" y en cada Triggers insertar el siguiente código

Insert Trigger = Hsts("AGREGAR")
update Trigger = Hsts("MODIFICAR")
delete Trigger = Hsts("ELIMINAR")

4 - Listo después de esto entonces cada transacción se estará grabando el la tabla de Historial, solo faltaría hacer un reporte para visualizar informacion del historial

Mauricio Mijangos Villalobos