Modificar puerto HTTP para Oracle XE

Problema

Cuando se instala el SGBD Oracle XE para desarrollo en un entorno local se instala con un servidor de aplicaciones desplegado en el puerto 8080. Este comportamiento es muy molesto cuando queremos usar un servidor tomcat o desplegar aplicaciones spring boot.

Pero es muy sencillo de arreglar, basta abrir una sesión en sqlplus y ejectuar el comando (EXEC DBMS_XDB.SETHTTPPORT(numero_puerto)):

$ sqplus system/XE

SQL*Plus ...
SQL> Exec DBMS_XDB.SETHTTPPORT(9090);
PL/SQL procedure sucessfully completed.

OJO: si queremos deshabilitar el servidor:

EXEC DBMS_XDB.SETHTTPPORT(0)

Referencias:

Referencias vistas el 24 de sep de 2018:

Audit Log con Entity Framework (.NET)

Introducción

Cuando desarrollamos aplicaciones de una cierta envergadura debemos de plantearnos usar ciertos patrones de diseño que garantizen la escalabilidad, robustez,  tolerancia a fallos y auditen nuestra aplicación.

Vamos a ver cómo usar el patrón Audit Log para auditar los eventos y operaciones de la aplicación.

Un audit log es un registro de las acciones que ocurren sobre una aplicación con unos datos (una entidad, una colección, un VO, …) y registra cuando ocurre una operación, quien ha sido el responsable, qué operación ha realizado y se puede incluir la información modificada (en su estado inicial y el modificado).

Para leer más sobre audit log leer el enlace adjunto de Martin Fowler.

Otro de los problemas cubiertos en esta entrada es cómo obtener el nombre de la tabla / vista de una entidad en entity framework.

Caso

Supongamos que tenemos una tabla PRODUCTOS sobre un SGBD Oracle y hemos desarrollado una aplicación basada en microservicios con .NET. Además hemos decidido utilizar el ORM Entity Framework como capa de abstracción para el acceso a datos.

Problemas que se presentan:

  • Cómo usamos un ORM contra un SGB, ¿cómo obtener el nombre de la tabla?
  • ¿Cómo implemento el audit log

Solución

Obtener el nombre de la tabla en EF

En Entity Framework, al definir una clase como una entidad de base de datos se anota con el decorador Table para indicar la tabla de base de datos (sino se llama igual que la clase), por ejemplo:

[Table("PRODUCTOS", Schema = "MI_BASE_DE_DATOS")]
public partial class Producto
{
    [Key]
    public int Id { get; set; }
    [StringLength(100)]
    public string Nombre { get; set; }
    ...
}

Esta clase representa nuestro producto mapeado em la base de datos. Al ser una entidad, si hacesmos un ToString() sobre su tipo, obtenemos el SQL que infiere Entity Framework para realizar consultas:

Set(typeof(Producto)).ToString()

Generando el siguiente SQL:

SELECT
“Extent1″.”Id” AS “Id”,
“Extent1″.”Nombre” AS “Nombre”,

FROM “MI_BASE_DE_DATOS”.”PRODUCTOS” “Extent1”

Con lo que podemos implementar una función de utilidad para obtener el nombre de la tabla para cada entidad:

public string GetTableName(Type entityType, bool debug = false)
{
  string sql = Set(entityType).ToString();
  if (debug)
    Console.WriteLine("La consulta SQL es: {0}", sql);
  Regex regex = new Regex(@"FROM\s+(?<table>.+)\s+");
  return regex.Match(sql).Groups["table"].Value;
}

Implementación sencilla del auditlog

Para implementar el auditlog hay que tener en cuenta una cuestión, ¿qué sistema de loggijng usamos? Log4net, uno propio, mongodb, elasticsearch, stdout … Vamos a hacer un sencillo ejemplo con stdout (modificar el ejemplo es llamar a nuestro servicio de logging).

public void auditLog(int userid, string operation, string table, string message = null)
{
  Console.WriteLine(string.Format(LOG, DateTime.Now, userid, operation, table, message));
}

LOG es una constante de cadena con el formato de la línea de log, por ejemplo:

const string LOG = “{0} – UserId = {1:D6} [{3} – {2}] – {4}”;

Cuya salida podría ser:

05/11/2018 12:50:18 – UserId = 012345 [“MI_BASE_DE_DATOS”.”PRODUCTOS” – DELETE] – Se ha borrado un registro

A partir de aquí, muchas opciones, soluciones y formas de adaptar el problema a una solución particular.

Referencias

Obtener contenido binario en un Select en Informix

Ver hexadecimal en Informix

En ocasiones resulta interesante poder ver el cotenido de un campo de base de datos en binario (o hexadecimal). Por ejemplo para tema de charsets, o por verificar la forma de almacenarlo.

En infromix tenemos una manera de hacerlo muy sencillo:

SELECT CAST(nombre_campo AS BYTE)
FROM nombre_tabla
WHERE expresion_condicion;

Un ejemplo de resultado:

(nombre_del_campo)                                        
----------------------------------------------------
af  61  6c  75  7a  6a  65  20  64  72  65  77  6e  
52  6f  6c  65  74  79  20  70  6c  65  63  69  6f

Espero que resulte útil.

Referencias

CAST Expressions: (visto 6 de julio de 2017) https://www.ibm.com/support/knowledgecenter/en/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0191.htm

Configurar proxy para Atom

Problema

En el trabajo usamos un proxy como en muchas grandes empresas. Uno de los diferentes editores que so es Atom (https://atom.io/). Y el problema es para instalar cualquier nueva características como un paquete, tema, etc.

Al acceder al gestor de paquetes (pulsar CTRL + COMA) y buscar un paquete no podremos instalarlo. En ese caso obtendremos el error:

tunneling socket could not be established, cause=connect ETIMEDOUT 192.169.35.2:3000

Solución

Para solucionarlo debemos configurar el gestor de paquetes de atom (APM) y esto sólo se puede hacer desde consola:

apm config set proxy "http://localhost:3128"
apm config set https_proxy proxy "http://localhost:3128"

Hecho esto, abrimos Atom y a trabajar:

Referencias

Deshabilitar ImprPant en Dropbox y habiitar en Greenshot

Greenshot es una herramienta muy útil para capturar la pantalla, zonas o ventanas en Windows.Pero cuando lo instalamos a la vez con Dropbox tenemos un problema con el uso de la tecla ImprPant.

El problema viene cuando YA está instalado Dropbox. Siguiendo los pasos de la ayuda de Dropbox encomtraremos cómo solucionarlo. Deshabilitamos el uso de la tecla Impr Pantalla de Dropbox y luego instalamos Greenshot para que éste use esa tecla como capturador estándar.

Organizar correos de Gmail por tamaño

Estoy organizando en mis ratos libres Gmail, porqué aunque Google ofrece mucho espacio es verdad que hay muchos correos con “basura” de la época en que se mandaba todo por email.

He encontrado la entrada muy útil con filtros para buscar en Gmail correos con ficheros adjuntos de un tamaño aproximado (alrededor de 15MB):

size:15mb

O ficheros con tamaños comprendidos entre:

larger_than:5m smaller_than:8M

A mi me ha sido muy útil.

Obtener vistas relacionadas en Oracle

Introducción

En ocasiones estamos manejado vistas o elementos de PL/SQL que necesitamos saber que relación existe entre ellos. Para esto oracle nos ofrece la vista user_dependencies que relaciona un objeto (vista, package, function, procedure) con otro si éste es dependencia de otro.

Caso de pruebas

Supongamos una vista ALUMNOS que se usa para hacer consulta, se consume en 1 procedure y 1 function. Si ejecutamos una consulta como la siguiente:


SELECT * FROM user_dependencies
  START WITH name = 'ALUMNOS'
  CONNECT BY PRIOR TRIM(referenced_name) = TRIM(name);

Obtendremos un resultado como el siguiente, donde veremos en la columna de la izquierda para cada ocurrencia de la izquierda en que elemento de la derecha esta como una dependencia.

Referencias

  1. USER_DEPENDENCIES:
    https://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_5252.htm
  2. ALL_DEPENDENCIES:
    https://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_1066.htm#i1576452

Desinstalar McAfee (Agent)

Introducción

Cuando compras un equipo nuevo de HP en ocasiones tienen la mala costumbre de traer software adicional instalado. En este caso el el antivirus McAfee VirusScan y su agente. Desinstalarlo no es fácil. No te permite hacerlo en una sesión normal y en modo a prueba de errores no se puede lanzar el servicio de Windows Installer. ¿Cómo hacerlo?

Desinstalar

En el enlace [1] se proporciona una forma de hacerlo (imagino que para equipos de 32 bits) en mi caso mi máquina es de 64 bits y viene instalado en la URL:

C:\Program Files\McAfee\Agent\x86

En esta carpeta abrimos una ventana de comandos (botón derecho + CTRL) y escribimos:

frminst.exe /remove=agent

Nos preguntará, contestamos que sí y a esperar que termine el prceso.

Referencia

  1. [BLOG de .josepros.com]: http://www.josepros.com/2010/02/desinstalacion-manual-de-mcafee.html

SQL Join: ¿Cual usar?

Introducción

Hace unos días tuve una conversación muy recurrente entre desarrolladores de software respecto del uso cotidiano de SQL. ¿Cómo usar JOIN? Esta duda la tienen aún desarrolladores expertos, pues bien vamos a aclarar un poco que es eso del JOIN.

Como breve resumen, decir que JOIN se usa en SQL para combinar filas de dos o más tablas. Y es una sentencia con tantas posibilidades que realmente se merece una explicación en una única entrada de este blog.

La sentencia JOIN como una expresión algebraica

Si tomamos cada tabla de la base de datos como un conjunto de datos donde cada columna posee su propio dominio definimos el operador como el JOIN para el conjunto de tuplas a relacionar (no deja de ser una composición):

De modo que R y S son dos tablas, y t y s son filas de cada tabla que se unirán si se cumple la condición dada. Y lo más fácil es ver el siguiente dibujo que representa los diferentes tipos de JOINS que existen conceptualmente (no todas los sistemas gestores de base de datos los soportan) y su representación aproximada como diagrama de Venn:

En este dibujo podemos ver gráficamente la idea de cada tipo de JOIN, filas que se relacionan en ambas tablas (conjuntos), filas que no tengan relación y estén en una tabla pero sí en la otra. O al revés, filas que no estén en la primera tabla y sí en la segundo, y en fin … todas las combinaciones que muestra el gráfico.

Por cierto, si se hace una composición de dos tablas con JOIN y la fila compuesta devuelta es resultado de una relación donde para una tabla hay datos y en la segunda tabla no existe relación, los campos de esa segunda tabla devueltos serám NULL.

Para leer más sobre algebra relacional recomiendo los apuntes de Pedro Pablo Alarcón Cavero [4], buen material docente sin duda. Pero todo esto es mejor analizarlo con un buen ejemplo.

Caso práctico

Si accedemos a la Web de W3Schools, tiene una base de datos de ejemplo donde podemos probar online difernetes sentencias SQL [Acceso a la BD en W3Schools].

Tablas de datos básicas

En este apartado primero vamos a ver una muestra de los datos que contienen las tablas, en la mayoría de casos vamos a ver una SELECT y los primeros registros que devuelve la base de datos, para mas información consultar el enlace “Acceso a la DB de W3Schools”.

Listado de Clientes

select * from Customers
CustomerID CustomerName ContactName Address City PostalCode Country
1 Alfreds Futterkiste Maria Anders Obere Str. 57 Berlin 12209 Germany
2 Ana Trujillo Emparedados y helados Ana Trujillo Avda. de la Constitución 2222 México D.F. 05021 Mexico
3 Antonio Moreno Taquería Antonio Moreno Mataderos 2312 México D.F. 05023 Mexico

(Devuelve 91 clientes)

Listado de Empleados

select * from Employees
EmployeeID LastName FirstName BirthDate Photo Notes
1 Davolio Nancy 1968-12-08 EmpID1.pic Education includes a BA in psychology from Colorado State University. She also completed (The Art of the Cold Call). Nancy is a member of ‘Toastmasters International’.
2 Fuller Andrew 1952-02-19 EmpID2.pic Andrew received his BTS commercial and a Ph.D. in international marketing from the University of Dallas. He is fluent in French and Italian and reads German. He joined the company as a sales representative, was promoted to sales manager and was then named vice president of sales. Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association.

(Devuelve 10 empleados)

Listado de Transportistas

select * from Shippers
ShipperID ShipperName Phone
1 Speedy Express (503) 555-9831
2 United Package (503) 555-3199
3 Federal Shipping (503) 555-9931

(Devuelve 3 transportistas)

Listado de Pedidos

select * from Orders
OrderID CustomerID EmployeeID OrderDate ShipperID
10248 90 5 1996-07-04 3
10249 81 6 1996-07-05 1
10250 34 4 1996-07-08 2

(Devuelve 196 pedidos)

Obtener los pedidos de cada cliente

Este es el ejemplo que ofrece W3SChools:

SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
OrderID CustomerName OrderDate
10248 Wilman Kala 1996-07-04
10249 Tradição Hipermercados 1996-07-05
10250 Hanari Carnes 1996-07-08
10251 Victuailles en stock 1996-07-08

(Mostramos los 4 primeros, hay 196 resultados)

Obtener los clientes que nunca han hecho un pedido

Ahora vamos a pensar en la tabla clientes y en pedidos. En pedidos se registran los pedidos y qué cliente lo realiza, pero … ¿cómo saber qué clientes no han hecho aún un pedido?

SELECT c.CustomerID AS CodigoCliente, c.CustomerName, o.CustomerID AS ClienteEnPedido
FROM Customers AS c
LEFT JOIN Orders AS o ON c.CustomerID=o.CustomerID
WHERE o.OrderID IS NULL;
CodigoCliente CustomerName ClienteEnPedido
1 Alfreds Futterkiste null
6 Blauer See Delikatessen null
12 Cactus Comidas para llevar null
22 FISSA Fabrica Inter. Salchichas S.A. null
26 France restauration null
32 Great Lakes Food Market null
40 La corne d’abondance null
42 Laughing Bacchus Wine Cellars null
43 Lazy K Kountry Store null
45 Let’s Stop N Shop null
50 Maison Dewey null
53 North/South null
57 Paris spécialités null
64 Rancho grande null
74 Spécialités du monde null
78 The Cracker Box null
82 Trail’s Head Gourmet Provisioners null

De los 91 clientes que hay, estos 17 no tiene pedidos realizados. Además podemos ver cómo la columna con el ID de cliente en pedidos obtenida con este JOIN vale NULL, con lo que sabemos que existe relación.

Obtener los empleados que no han hecho ventas

Este es otro ejemplo cómo el anterior:

SELECT e.EmployeeID, e.FirstName
FROM Employees AS e
LEFT JOIN Orders AS o ON e.EmployeeID=o.EmployeeID
WHERE o.EmployeeID IS NULL;
EmployeeID LastName FirstName BirthDate Photo Notes
10 West Adam 1928-09-19 EmpID10.pic An old chum.

Adam West es el único cliente que no ha registrado pedidos en la base de datos.

Obtener qué pedidos ha hecho Nancy

Este caso es el mismo que obtener los pedidos de cada cliente, pero añadiendo un flltro por empleado.

SELECT e.EmployeeID, e.FirstName, o.OrderID
FROM Employees AS e
INNER JOIN Orders AS o ON e.EmployeeID=o.EmployeeID
WHERE e.FirstName = 'Nancy';
EmployeeID FirstName OrderID
1 Nancy 10258
1 Nancy 10270
1 Nancy 10275
1 Nancy 10285
1 Nancy 10292

Muestro los 5 primeros pedidos, pero Nancy ha hecho 29 pedidos.

Conclusión

JOIN es una clausula para las consultas SELECT que enrique mucho el lenguaje SQL, permite realizar consultas para diferentes casos muy interesantes sin tener que recurrir a escribir consultas muy complicadas.

Ejemplos para analizar el uso de JOIN hay muchos y en Google podemos encontrar muchos, espero que este resumen sirva de ayuda.

Referencias

  1. Join en Wikipedia: http://es.wikipedia.org/wiki/Join
  2. Join en W3SChoolshttp://www.w3schools.com/sql/sql_join.asp
  3. Manual de MySQL5 – Sentencia JOIN: http://dev.mysql.com/doc/refman/5.0/es/join.html
  4. Para leer algo más sobre algebra relacional (con permiso de Pedro Pablo Alarcón Cavero ): http://www-oei.eui.upm.es/Asignaturas/BD/BD/docbd/tema/algebra.pdf

Resetear el password del root en mysql

Solución rápida

¿Qué ocurre si instalas un servidor MySQL y no recuerdas al password del usuario root? O mejor aún, ¿y si te descargas una aplicación que preinstala un WAMP o XAMP y no te indica cual es el password de root?

Bueno, es un contratiempo pero no está todo perdido, si trabajamos en un entorno Unix podemos hacer los siguiente:

1. Detener el servidor

service mysql stop  o  /etc/init.d/mysqld stop

2. Iniciar el servidor en modo seguro:

mysqld_safe --skip-grant-tables --skip_networking &
  • La primera opción sirve para deshabilitar los permisos sobre las tablas y todos los usuarios pueden acceder a todas las tablas
  • La segunda acción deshabilita el servidor sobre TCP, de modo que el servidor sólo funciona de forma local (es una forma algo segura de manejar el servidor “a prueba de fallos” evitando que nadie desde la red se encuentre manipulando tablas o bases de datos que no debería tocar.

3. Iniciar el cliente CLI (TUPASWORD es la cadena de contraseña a elegir, además ver que se debe cifrar con PASSWORD() que es la función de cifrado para contraseñas por defecto de MySQL)

$ mysql -uroot
mysql> use mysql;
mysql> update user set passoword=password('TUPASSWORD') where user='root';

4. Por último queda reinicar el servidor.

Referencias