martes, 16 de diciembre de 2008

ORA-00942 La tabla o vista no existe (pero sí existe)

Este error nos ha salido a muchos y generalmente se presenta cuando realmente la tabla o vista no existe en el esquema en el que la queremos usar.

Pero otras veces se genera porque no se han dado los permisos necesarios hacia la tabla o vista, o porque estamos intentando referenciar la tabla sin su esquema (cuando pertenece a otro) y el motor de base de datos se confunde si hay otro objeto en la base de datos con el mismo nombre.

Sin embargo, aunque la tabla exista y aunque se tengan los permisos necesarios para acceder a ella y se use el nombre del esquema al que pertenece, todavía existe la posibilidad de que nos salga el error ORA-00942. Resulta que si los permisos sobre la tabla o vista son concedidos a un rol al que pertenece el usuario con el que necesitamos accederla, es posible ejecutar query's normalmente. Pero si estos query's se van a ejecutar dentro de un procedimiento almacenado, nos vamos a encontrar con ORA-00942.

Qué pasa?
Pues no sé si sea un bug en el RDBMS, o esa sea su forma de administrar los privilegios o tal vez es por razones de seguridad, pero para poder acceder a una tabla o vista desde un procedimiento almacenado, el usuario debe haber adquirido los privilegios directamente y no a través de un rol.

miércoles, 15 de octubre de 2008

Cómo ordenar colecciones de objetos en java

Ordenar colecciones de objetos en java es muy sencillo, basta con hacer un cambio en la clase de los objetos que se van a agregar en la colección.
El cambio consiste en implementar la interface java.lang.Comparable, la cuál nos obliga a implementar únicamente el método compareTo(Object objeto2) de forma que devuelva un entero. El valor devuelto por este método debe ser el equivalente a this - objeto2.

Ejemplo:
public class Articulo implements Comparable {

private String nombre;
private Double valor;

public String getNombre() {
  return nombre;
}

public void setNombre(String nombre) {
  this.nombre = nombre;
}

public Double getValor() {
  return valor;
}

public void setValor(Double valor) {
  this.valor = valor;
}

public int compareTo(Object objeto2) {
  Articulo articulo2 = (Articulo) objeto2;
  return this.valor.compareTo(articulo2.getValor());
}

}
En este ejemplo se hace uso del método ya implementado por parte de la clase Double, pero la implementación la pudimos haber hecho de la manera en que más nos convenga.

Después, suponiendo que articulos es una colección de Articulos, podemos hacer:
Collections.sort(articulos);
Y nuestra lista de artículos quedará ordenada.

martes, 7 de octubre de 2008

Internet Explorer y cookies remotas

Una vez más, problemas por culpa de Internet Explorer...

Resulta que a los "genios" desarrolladores del navegador (?) se les ocurrió una grandiosa idea: tratar a las cookies de un sitio cargado dentro de un iframe, como cookies de terceros.

Por ejemplo, tenemos el sitio www.sitiouno.com y dentro de este queremos cargar un iframe con el sitio www.sitiodos.com. El sitio sitiodos envía una cookie al navegador y cuando se ingresa de forma normal a él, el sitio tiene un funcionamiento normal. Al entrar a sitiouno con Internet Explorer se recibe la cookie, pero ésta es tratada como una cookie de terceros.

El problema de que la cookie sea tratada de esa manera es que regularmente los usuarios tienen configurado su IE en un nivel de privacidad medio, el cual "Bloquea cookies de terceros que no tienen una directiva de seguridad sólida". Este bloqueo consiste en que la cookie es eliminada, es decir, no es tomada en cuenta por el maravilloso navegador y generar una experiencia no muy grata para el usuario.

Para corregir este problema de forma rápida, basta con agregar una política de privacidad compacta en las cabeceras de la respuesta antes de intentar crear la cookie. La forma de hacer esto es:

En PHP:
<?php
header('P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
?>
En Java:
httpservletresponse.setHeader("P3P","CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");
Cada conjunto de letras tiene un significado y uno lo puede adaptar según a la forma en la que quiera definir su política de privacidad. El anterior ejemplo funcionó muy bien para el problema que tuvimos nosotros, pero en http://www.w3.org/P3P/implementations.html se encuentra software para crear, editar y probar estas políticas a la medida de las necesidades. También está este formulario http://www.dmaresponsibility.org/PPG/, que genera la política según las respuestas que demos.

El problema se presenta de la versión 6 en adelante.

Bueno, ese fue el camino corto. El camino largo requiere permiso de cambiar la instalación de Apache para poder instalar mod_header y acceso a los archivos de configuración. Aunque la solución larga no la probamos, si encontramos bastante información:

Los seis pasos para crear y publicar la P3P:
http://www.w3.org/P3P/details.html

Estos son más detallados:
http://www.windley.com/archives/2008/08/p3p_and_internet_explorer.shtml
http://www.builderau.com.au/architect/webservices/soa/Implementing-privacy-preference-policies-with-P3P/0,339024590,320264989,00.htm

Acá les dejo más información:
http://www.w3.org/P3P/
http://www.webmasterworld.com/forum21/788.htm

miércoles, 24 de septiembre de 2008

Cómo incrementar el valor de una secuencia

El siguiente PL/SQL es útil para incrementar el valor de una secuencia al valor que deseemos:
DECLARE
i NUMBER(10);

BEGIN

  SELECT SQCUENTA.NEXTVAL INTO i FROM dual;

  WHILE i < 1000000 LOOP 
    SELECT SQCUENTA.NEXTVAL INTO i FROM dual; 
  END LOOP;
END;
Esto me ha funcionado en una BD Oracle 10g.

En PostgreSQL existe la función setval que permite hacer lo mismo.
SELECT setval('SQCUENTA', 1000000);