diciembre 28, 2005

Nulos e Integridad Referencial

Trabajando en un proyecto reciente me encontré con este detalle que parece tener Firebird (al menos en las versiones 1.5.2 y hasta el 1.5.3 RC3 que es la que tengo en mi laptop). Resultó ser ese tipo de cosas que te encuentras y que te pueden tomar muchas horas en dilucidar en donde es que radica el problema y resulta ser algo risorio y que se le ha escapado a alguien en el desarrollo de Firebird.

Para empezar he de explicar el escenario donde me ocurrió esto, tengo una tabla llamada GESTORES donde a cada gestor se le puede o no asociar un usuario del sistema, entonces hay registros que tienen un valor en este campo y otros en los que simplemente se queda en nulo. Dado esto, en teoría esta consulta me debería dar todos los usuarios que no estan asociados a algún gestor:


Sin embargo, no fué así, esta consulta no me devolvía ni un solo valor aunque yo sabía que si habian por lo menos 15 usuarios que no estaban asociados a algún gestor.

De repente algun Dios olimpico iluminó mi mente y me llego la idea de que tal vez el hecho de que hubiera valores nulos en la tabla de gestores influiría, así que le agregué una pequeña condición para ignorar los valores nulos de la relación:


Con esto ya funcionó sin ningún problema el programa, ahora si me devolvía los 15 registros de los usuarios que no estaban asociados a gestores.

Pero la duda me aquejaba acerca de si esto era una constante en las relaciones WHERE NOT IN asi que me leí el magnífico artículo de Firebird Nulls Guide del sitio de Firebird, en el cual se explica mucho acerca del comportamiento de los valores nulos en las comparaciones y operaciones con Firebird, pero nada que me diera un Norte sobre porque mi consulta especificamente tenia un comportamiento tan errático. Probé con otras tablas de la misma base de datos y solo con estas dos me devolvia un conjunto vacío. Al rebuscar más meticulosamente cai en la cuenta de que la diferencia radicaba en que no había definido una regla de integridad referencial entre los campos de ambas relaciones, asi que raudo y veloz procedí a crearla:


Y una vez hecho esto ya la primer consulta funciona perfectamente. Osea que al final de cuentas el problema es que la combinación de comparación del tipo WHERE [NOT] IN SELECT falla cuando en el subselect existen valores nulos y no hay una relación de integridad entre ambas relaciones, esto pareciera trivial, pero cuando en un sistema tratas de explotar al máximo los datos que tienes las consultas de este tipo suelen ser muy comunes y si tienes un sistema de consultas dinámicas o algun experto programado que haga estas consultas puede caer muy fácilmente en estos casos y no ser validado.

Entonces como conclusión de todo esto podemos emitir la siguiente sentencia:

¡Cuidado con Firebird! porque la combinación de comparación del tipo WHERE [NOT] IN SELECT falla cuando en el subselect existen valores nulos y no hay una relación de integridad entre ambas relaciones.


Pueden hacer sus pruebas en sus propias configuraciones y ver que otras implicaciones tiene este detalle, esperemos que esto se arregle pronto.

Delphi del 1 al 10 Where version <> 8

¿Cual es su favorito?







diciembre 22, 2005

Escribir en el Canvas de un componente

Eneko alonso es un joven programador de Delphi que en su página web nos comparte esta muy útil funcion que permite escribir sobre el Canvas de algun componente en nuestras aplicaciones, pero les dejo que sean sus propias palabras quienes les expliquen el truco:
Para escribir texto transparente sobre el canvas de cualquier componente visual en Delphi, hay que usar la función SetBkMode de la API de Windows.

procedure TForm1.Button1Click(Sender: TObject);
var
AnteriorBkMode: integer;
begin
with Form1.Canvas do begin
Brush.Color := clRed;
TextOut(100, 80, 'Texto Opaco');
AnteriorBkMode := SetBkMode(Handle, TRANSPARENT);
TextOut(100, 100, 'Texto Transparente');
SetBkMode(Handle, AnteriorBkMode);
end;
end;

La directiva de proyectos

Por lo menos estamos en buenas manos

diciembre 14, 2005

Una cadena = Un número único

Esta función me pareció tres cosas: útil, interesante y sencilla

type
  UInt64 = 0..9223372036854775807;

  function Unc (s: string): UInt64;
  var
    x: integer;
  begin
    Result := 0;
    for x := 1 to Length (s) do
    begin
      Result := Result + ((Ord (s[x])) shl ((x - 1) * 8));
    end;
  end;

La lógica detrás de la función no es complicada, si bien si muy práctica y útil en varios casos cuando al manejar elementos en memoria interesa obtener identificadores únicos por alguna serie de textos ( me he encontrado con casos así al trabajar con sistemas de redes o árboles). Un inconveniente es que los números que se obtienen por esta función son muchas veces números muy grandes (de hasta 64 bits) por lo que la aplicación en una BD como Firebird por ejemplo resulta un tanto complicada; pero bueno no es tan fácil tenerlo todo siempre.

diciembre 04, 2005

Todo mundo tiene su estilo

Es muy sabido que en esta vida todo mundo tiene su propio estilo para programar, cada quien se entiende con sus propios garabatos. Hay a quienes les gusta hacer miles y miles de funciones(y luego de tantas que tienen ni se acuerdan que las tienen cuando necesitan una en particular), otros que son muy metódicos en cuanto al número de lineas que ha de contener un proceso, otros que cuidan que en tal o cual paso la pila del procesador no tenga mas de X retornos acumulados de procedimientos o funciones, O que les gusta ahorrar hasta el mas ínfimo bit de memoria y otros a quienes les vale un soberano grano de café molido ese asunto y prefieren sacrificar mucha memoria para darle mayor enfasis a alguna otra funcionalidad de la aplicación.

Mas de una vez me ha tocado descifrar marañas entretejidas de cosas que parecen no tener mucho sentido pero como diría Galileo
"Sin embargo funcionan..."


Mas tambien sin embargo es un verdadero martirio darle seguimiento y mantenimiento a aplicaciones escritas así, la mayoría de las veces que eso me sucede y mientras pueda hacerlo prefiero reescribir el módulo o aplicación a mi manera

Y es que realmente uno se acostumbra a trabajar con su propio estilo, a identar de tal o cual manera su código, a seguir ciertas normas, a ignorar algunas otras, etc...Y no solo en cuanto a Código en Object Pascal, sino tambien en el caso de las consultas en SQL, las politicas de mantenimiento y desarrollo sobre la estructura y código en la Base de Datos, en fin.

Pero a todo esto, existen ciertos estandares que fincan por ejemplo las empresas de desarrollo para que el trabajo de su personal sea lo mas colaborativo y transparente posible. Por eso llamó mi atención la publicación que encontré de los estandares que usan en Indy con los que comparto mucha afinidad y de los que debería tomar algunas notas en cuenta y agregarlas en mi propio estilo. Otros muy buenos estandares son los propuestos por Marco Cantu en sus 20 reglas para la OOP en Delphi, las cuales se publicaron en la Delphi Magazine, que andan por ahi volando en algunos sitios, pero desconozco si esta permitida su distribución abierta

noviembre 28, 2005

Yonders GLScene


Yonders
La página de Yonder es un buen repositorio de demos sobre GLScene, los demos estan bajo el esquema anterior de GLScene es decir que usan la nomenclatura antigua, pero con unos pocos retoques podemos hacerlos funcionar sin problemas sobre las nuevas versiones

Demos como el del submarino y el de la nave espacial son muy elaborados valen mucho la pena estudiarlos

Que esperar en 2006 para firebird

Este es el verdadero Roadmap publicado para Firebird

Entre las muchas cosas que han llamado mi atención estan el uso de indices bidireccionales y la incorporación de FullTextSearch, que hasta ahora habia que usar herramientas de terceros para su implementación en Firebird.

La lista de características que contendrá la segunda versión de Firebird merece que le dediquemos un ratito para ver ahora con que herramientas contamos.

noviembre 14, 2005

DelphiMan


Dichoso y aleluyo me encuentro hoy pues por fin recibí mi preciada versión plástica de "DelphiMan!!!!"... Hoy recibí un paquete directamente desde Borland Inglaterra (UK) en el cual se me felicitaba por haber sido uno de los escasos 2000 agraciados que contarán con el famoso superheroe del software, pero eso no era todo, quesque por ser de los primeros primerisimos en registrarme en la web de DelphiSuperHero tambien me enviaban al mismisimo Dr Dead Line, con todo y su cinturon repleto de Bugs y al Delphiman con su "depurador atómico integrado"... en fin, que ahora no quepo en el calzón de la emoción... y como le digo a mis compañeros de trabajo: "No, no es un mono inflable, es una 'figura de Acción', Ok???..."

noviembre 04, 2005

Comparacion de OS DBMS

Esta es una comparativa de diferentes manejadores de bases de datos Open Source, imparcial a mi parecer, aunque no muy actualizada ni fidedigna en sus afirmaciones... de cualquier modo es un muy buen documento de referencia...

Compara:

  • Firebird 1.5.2

  • Ingres r3 3.0.1

  • MaxDB 7.5.0.23

  • MySQL 4.1.10

  • PostgreSQL 8.0.1

CnWizards

Solo cosas buenas tengo que decir de los CnWizards...

Desde hace ya varios ayeres, tengo como ambiente de trabajo la versión 6 de Delphi... ¿que porque no me he cambiado a una versión mas reciente??... pues sencillo, porque no lo he necesitado, con lo que tiene la versión 6 me ha bastado y sobrado hasta ahora...

Y como yo se que hay muchos programadores alla afuera, pues para todos aquellos que como yo no hemos necesitado el cambio se hizo un paquete de expertos fenomenales que hacen el trabajo diario mas sencillo...

CnWizards son unos expertos realizados por un equipo de programadores chinos (asiaticos, no de rizos, por si la duda habia) que ofrecen poderosas y prácticas herramientas tanto en el editor de código como en el ambiente de desarrollo en general...

Si programas en Delphi 5,6 o 7 y extrañas el matcheo de parentesis que ofrece Delphi 2005 pues con estos expertos lo tienes, un Autocomplete mucho mas poderoso y rápido, simple manejo de marcadores (bookmarks), lineas de codigo numeradas, Tab Orders visuales en el diseñador de la forma, herramientas de alineación, estadisticas del proyecto, comparación de fuentes...en fin...

son cientos de características que mejoran considerablemente el ambiente de trabajo, personalmente creo que son bastante mas completos que los famosos GExperts, basta con ver una imagen para hacerse una idea de lo que estamos hablando.

Para mas información visiten el sitio de CnPack donde verán las cosas en las que estos chinos estan trabajando para el bien de toda la comunidad de desarrolladores de Delphi

noviembre 01, 2005

InterBase - Date functions


Esta página esta muy interesante, contiene muchas funciones que se pueden usar para el manejo de fechas con Interbase/Firebird, muy útil si pensamos que se dejan de usar algunas UDF's cuando se hace uso de estas sencillas instrucciones SQL

funciones de fechas

Por ejemplo Tomando a D como la fecha en cuestion:

Dia de la semana:
EXTRACT(WEEKDAY FROM D)
regresa 0=Domingo, 1=Lunes, 2=Martes...6=Sabado

Primer dia del mes:
D - EXTRACT(DAY FROM D) + 1;

Ultimo dia del mes:
D - EXTRACT(DAY FROM D) + 32 - EXTRACT(DAY FROM D - EXTRACT(DAY FROM D) + 32)

Primer dia del siguiente mes:
D - EXTRACT(DAY FROM D) + 33 - EXTRACT(DAY FROM D - EXTRACT(DAY FROM D) + 32)

Número de dias del mes:
EXTRACT(DAY FROM (D - EXTRACT(DAY FROM D) + 32 - EXTRACT(DAY FROM D - EXTRACT(DAY FROM D) + 32)))

Saber si es año bisiesto debe evaluar a true lo siguiente:
( 2 = EXTRACT(MONTH FROM (D - EXTRACT(YEARDAY FROM D) + 59)) )

La semana del año empezando la semana en Lunes:
(EXTRACT(YEARDAY FROM D) - EXTRACT(WEEKDAY FROM D-1) + 7) / 7