israeldavidvm / database-auditor
¡Optimiza tu diseño de bases de datos con data-auditor! ¿Quieres asegurarte de que tu base de datos esté libre de redundancias, anomalías y problemas de diseño? Con data-auditor, obtén las herramientas necesarias para validar formas normales, analizar dependencias funcionales y garantizar un diseño
Requires
- php: >=5.4
- symfony/console: >=5.1
- vlucas/phpdotenv: >=5.3.0
README
Table of Contents generated with DocToc
- data-auditor
- ¡Optimiza tu diseño de bases de datos con data-auditor!
- Licencia
- Caracteristicas ¿Qué te ofrece data-auditor?
- Challenges conquered / Desafíos Conquistados
- Features to implement / Caracteristicas a implementar
- Planning, Requirements Engineering and risk management / Planeacion, Ingenieria de Requerimientos y gestion del riesgo
- Software Design / Diseño de Software
- Verification and Validation / Validacion y Verificacion
- Formal validation / Validacion Formal
- Documentacion
- Technologies used / Tecnologias usadas
data-auditor
¡Optimiza tu diseño de bases de datos con data-auditor!
¿Quieres asegurarte de que tu base de datos esté libre de redundancias, anomalías y problemas de diseño? Con data-auditor, obtén las herramientas necesarias para validar formas normales, analizar dependencias funcionales y garantizar un diseño robusto y eficiente. ¡Prueba nuestra interfaz de línea de comandos y lleva tu base de datos al siguiente nivel!
Licencia
Este código tiene licencia bajo la licencia pública general de GNU versión 3.0 o posterior (LGPLV3+). Puede encontrar una copia completa de la licencia en https://www.gnu.org/licenses/lgpl-3.0-standalone.htmlalone.html0-standalone.html
Caracteristicas ¿Qué te ofrece data-auditor?
data-auditor es una herramienta integral diseñada para evaluar y optimizar la calidad de tus diseños de bases de datos. Ofrece un conjunto de funcionalidades avanzadas que incluyen:
Validación de formas normales: Asegura que tu diseño cumpla con las primeras tres formas normales, minimizando la redundancia y evitando anomalías en las actualizaciones.
Comprobación de la propiedad de concatenación no aditiva: Detecta posibles problemas de diseño que podrían afectar los resultados de las consultas.
Análisis de dependencias funcionales: Facilita la comprensión de las relaciones entre los atributos de las tablas, permitiendo un diseño más robusto y eficiente.
Interfaz de línea de comandos: Proporciona una forma sencilla y directa de utilizar la librería, ideal para integración en flujos de trabajo automatizados.
Con data-auditor, podrás garantizar un diseño de base de datos sólido, eficiente y libre de errores comunes.
Challenges conquered / Desafíos Conquistados
- Demostracion formal de algoritmos
Features to implement / Caracteristicas a implementar
- Deteccion de errores en el diseño de la base de datos que afecten el funcionamiento de los algoritmos
- Valida que los nombres de tablas y atributos ingresados como entrada sean validos
- Soporte a nombres a atributos, tablas, fk y pk no convencionales
- Soporte a relaciones recursivas
Planning, Requirements Engineering and risk management / Planeacion, Ingenieria de Requerimientos y gestion del riesgo
Estas secciones del proyecto se llevara por medio de un sitio en notion de forma que puedan ser facilmente accesibles por el personal no tecnico.
Solicita el link de acceso al personal autorizado
Software Design / Diseño de Software
Perspectiva Estructural
Vista Logica de la Arquitectura del software
En el siguiente diagrama de clases se veran las abstracciones clave en el sistema, sus interaciones responsabilidades.
--- title: database auditor --- classDiagram class DatabaseAuditor{ } note for DatabaseAuditor "Busca ser el contexto para las distintas estrategias usadas y un medio que encapsula funciones utilitarias comunes para todos los algoritmos" DatabaseAuditor ..> DatabaseSchemaGenerator class DatabaseSchemaGenerator{ <<Abstract>> +databaseAuditor +generate() } note for DatabaseSchemaGenerator "Proporciona la interfaz estrategia que es común a todas las estrategias concretas para la generacion de los esquemas de la base de datos" DatabaseSchemaGenerator ..> SchemaFromDBUsingName DatabaseSchemaGenerator ..> SchemaFromJSON class SchemaFromJSON{ +databaseAuditor +generate() } class SchemaFromDBUsingName{ +databaseAuditor +generate() } note for SchemaFromDBUsingName "Es una de las estrategias concretas que genera los esquemas por medio de los nombres de las convenciones de nombres de la base de datos" DatabaseAuditor ..> ValidationAlgorithm note for ValidationAlgorithm "Proporciona la interfaz estrategia que es común a todas las estrategias concretas para la generacion de las validaciones de la base de datos" class ValidationAlgorithm{ <<Abstract>> +execute() } ValidationAlgorithm <|-- NonAdditiveConcatenation ValidationAlgorithm <|-- VerificationBCNF class VerificationNonAdditiveConcatenation{ +databaseAuditor +execute() } note for NonAdditiveConcatenation "Encapsula el Algoritmo 11.1 de Verificación de la propiedad de concatenación no aditiva propuesto por RAMEZ ELMASRI y SHAMKANT B. NAVATHE" class VerificationBCNF{ +databaseAuditor +execute() } note for NonAdditiveConcatenation "Encapsula el Algoritmo que valida que cada descomposicion posea la BCNF en base a la definicion presentada por RAMEZ ELMASRI y SHAMKANT B. NAVATHE" DatabaseAuditor <.. Client class Client{ }Loading
Perspectiva de comportamiento
SchemaFromDatabaseUsingName.generateJoinsClusters process / Proceso de SchemaFromDatabaseUsingName.generateJoinsClusters
--- title: Proceso de SchemaFromDatabaseUsingName.generateJoinsClusters --- stateDiagram-v2 getTables: obtener las tablas [*] --> getTables getTables --> foreachTables note left of foreachTables : "Esta actividad se ejecuta por cada tabla" state foreachTables { state if1 <<choice>> [*] --> relationtables=getTablesManyToManyRelationship(table) relationtables=getTablesManyToManyRelationship(table) --> if1 if1 --> manyToManyRelationshipAnalysis : relationtables!=null state manyToManyRelationshipAnalysis { state if2 <<choice>> [*] --> if2 if2 --> [*] : isRecursive(table) if2 --> addManyManyTable : else addManyManyTable: joinsClusters[last][]=manyToManytable addManyManyTable --> foreachRelationTables note left of foreachRelationTables : "Esta actividad se ejecuta por cada tabla que participa en la relacion mucho a mucho" state foreachRelationTables { addRelationTable: joinsClusters[last][]=relationtable [*] --> addRelationTable addRelationTable --> [*] } foreachRelationTables --> [*] } manyToManyRelationshipAnalysis --> normalRelationshipAnalysis if1 --> normalRelationshipAnalysis : relationtables==null state normalRelationshipAnalysis { [*] --> fks=getFKByTable(table) fks=getFKByTable(table) --> excludeManyToManyFk state if3 <<choice>> excludeManyToManyFk --> if3 if3 --> [*] : else addReferencingTable: joinsClusters[last][]=referencingTable if3 --> addReferencingTable : fks!=null addReferencingTable --> foreachFK note left of foreachFK : "Esta actividad se ejecuta por cada tabla que a la apunta una fk" state foreachFK { addReferencedTable : joinsClusters[]=referencedTable [*] --> addReferencedTable addReferencedTable --> [*] } foreachFK --> [*] } normalRelationshipAnalysis --> [*] }Loading
SchemaFromDatabaseUsingName.generate() process / Proceso de SchemaFromDatabaseUsingName.generate()
--- title: Proceso de SchemaFromDatabaseUsingName.generate() --- stateDiagram-v2 [*] --> getTables state getTables{ state if2 <<choice>> [*]-->if2 if2-->getTablesIncludeMode : mode==include getTablesIncludeMode-->[*] if2-->getTablesExcludeMode : mode==exclude getTablesExcludeMode-->[*] } getTables --> foreachTables note left of foreachTables : "Esta actividad se ejecuta por cada tabla" state foreachTables { [*] --> getColumnsFullyQualifiedForm note left of getColumnsFullyQualifiedForm : "Si una columna no es una llave foranea columnName=pluralToSingular(tableName).columnName" getColumnsFullyQualifiedForm --> foreachColumn note left of foreachColumn : "Esta actividad se ejecuta por cada columna" state foreachColumn { state if3 <<choice>> [*]-->if3 addColumnUniversalRelationship: "agregar Columna a la universalRelationship " addColumnTableDecomposition: "agregar Columna a la decomposition de la tabla " if3 --> addColumnUniversalRelationship : !columnInUniversalRelationship addColumnUniversalRelationship-->addColumnTableDecomposition if3 --> addColumnTableDecomposition : else addColumnTableDecomposition --> [*] } foreachColumn-->addTrivialFunctionalDependency state addTrivialFunctionalDependency{ addPkFunctionalDependency: si existe una pk agregar pk como antecedente a la dependencia funcional y los demas atributos como consecuente [*]-->addPkFunctionalDependency addPkFunctionalDependency-->[*] } addTrivialFunctionalDependency --> [*] }Loading
Verification and Validation / Validacion y Verificacion
Formal validation / Validacion Formal
getFunctionalDependenciesForBCNFInTable
El objetivo de esta sección es demostrar que el algoritmo puede utilizarse para generar el conjunto de dependencias funcionales necesario para validar la BCNF (Forma Normal de Boyce-Codd).
El nuevo algoritmo que presentaremos a continuación se basa en la idea de que, para aplicar la verificación de BCNF en cada descomposición, podemos utilizar el conjunto de dependencias funcionales en el que tanto el antecedente como el consecuente son subconjuntos del conjunto de atributos de la descomposición, en lugar de utilizar la proyección del conjunto de dependencias funcionales para esa descomposición, ya que esta última opción resulta ser mucho más exigente en términos algorítmicos
Para ello es importante tener en cuenta que
Un esquema de relación R está en BCNF si siempre que una dependencia funcional no trivial X → A se cumple en R, entonces X es una superclave de R.
BCNF Definition / Definicion BCNF
y que el conjunto de dependencias funcionales para una descomposicion es la proyeccion del conjunto de dependencias de la relacion universal proyectado para una descomposicion.
Es decir
Donde F+ es la Clasura de un conjunto de dependencias funcionales
Closing a set of Functional Dependencies / Clasura de un conjunto de dependencias funcionales
Formalmente, el conjunto de todas las dependencias que incluyen F, junto con las dependencias que pueden inferirse de F, reciben el nombre de clausuras de F; está designada mediante F+.
Inference Rules for Functional Dependencies / Reglas de inferencia para las dependencias funcionales
Recordemos que las reglas de inferencia bien conocidas para las dependencias funcionales son
Habiendo dicho esto notese que para las reglas de inferencia sucede lo siguiente al ser aplicados sobre el algoritmo de bcnf
Regla reflesiva
Para el caso de la regla reflexiva las dependencias funcionales generadas x->y requieren que x sea subconjunto de y de modo que solo genera dependencias triviales las cuales no se toman en cuenta en bcnf
Reglas transitiva, de descomposicion y union
Para el caso de las reglas transitiva, de descomposicion y union el antecedente de las dependencias funcionales no cambia de manera que si el antecedente es super clave la descomposicion cumplira la regla de BCNF en caso de que no sea super clave la descomposicion no cumplira la regla de BCNF es decir las descomposiciones inferidas con estas reglas no afectaran el resultado
Reglas de de aumento y pseudo-transitividad
Para el caso de las reglas de de aumento y pseudo-transitividad sucede que el antecedente X se une con otro conjunto W o Z en cualquiera de los casos sucede que: Si x es super clave solo se podran inferir reglas en las que el antecedente siga siendo super clave Si x no es super clave se podran inferir reglas que sean super claves pero en caso de que x no sea super clave ya sabremos que por la definicion de BCNF esta forma no se cumple.
En conclusion: Para el caso de la validacion de la BCNF podemos usar el
Documentacion
El paquete data-auditor permite realizar una serie de validaciones y mejoras a la calidad del diseño de una base de datos como la comprobacion de formas normales, verificación de la propiedad de concatenación no aditiva, etc.
Convenciones usadas durante la docuemntacion
Convenciones de notacion para la gramatica:
Los <> se utilizan para rodear un simbolo no terminal
El ::= se utiliza para reglas de produccion
Los simbolos no terminales se expresan como una cadena o caracteres normales
El siguiente grupo de pares de simbolos, se deben utilizar junto a las expresiones de la siguiente forma: el primero en cada pareja se escribe como sufijo despues de la expresion y el segundo rodea la expresion.
El ? o [] indican que la expresion es opcional
El * o {} indica que la expresion se repite 0 o mas veces
El + indica que la expresion se repite 1 o mas veces
Si se quiere usar uno de los caracteres anteriores se debe de anteceder \ con
Generacion de esquemas
Para que los algoritmos funcionen se debe de generar una representacion de la base de datos sobre la cual aplicar dichos algoritmos
Lamentablemente algunos SGBD, dan soporte a los estadares de sql de forma diferente por lo que no existe una algoritmo universal que funcione perfectamente para todos los SGBD.
De manera que el software se diseño tomando en cuenta la posibilidad de utilizar diferentes algoritmos. Mas concretamente se utilizara el patron strategy para permitir el intercambio de algoritmos
Las estructuras responsables para esto seran las siguientes:
DatabaseAuditor
Busca ser el contexto para las distintas estrategias usadas y un medio que encapsula funciones utilitarias comunes para todos los algoritmos
DatabaseSchemaGenerator
proporciona la interfaz estrategia que es común a todas las estrategias concretas para la generacion de los esquemas de la base de datos
SchemaFromDBUsingName
Es una de las estrategias concretas que genera los esquemas por medio de los nombres de las columnas de la base de datos
Si bien se pudo usar el conjunto de vistas de information_schema para determinar algunas de las estructuras de la base de datos
Se descubrio que en postgresql se suelen generar joins aditivos
Por ejemplo si se quisiera saber si una columna en la information_schema.key_column_usage es una PRIMARY KEY, FOREIGN KEY, etc, deberia usarse la consulta
SELECT kcu.column_name,kcu.table_name,tc.constraint_name,tc.constraint_type FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name
Sin embargo si observamos detenidamente dichos resultados se ven afectados por un join aditivo
Para el caso particular de tener
SELECT column_name,table_name FROM information_schema.key_column_usage WHERE table_name ~ '^insight_taxonomy$'
que arroja resultados de esta forma
y un
SELECT tc.constraint_name FROM information_schema.table_constraints tc WHERE tc.constraint_name ~ '^taxonomy_id_fkey$'
que arroja resultados de esta forma
se tiene que el
SELECT kcu.column_name,kcu.table_name,tc.constraint_name,tc.constraint_type FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name WHERE kcu.table_name ~ '^insight_taxonomy$'
genera los siguientes resultados que reflejan el join aditivo
Convenciones de nombres usada para la identificacion de elementos
Llaves Primarias
Todo atributo de nombre id
Ejemplos
id
Llaves Foraneas
Todo atributo que posee la siguiente forma
<nombreTablaSigular>[_<rol>]_id
Donde [rol] sirve para identificar a la entidad en las relaciones recursivas
Coincide con la siguiente expresion regular
^[a-zA-Z0-9ñ]+(?:_[a-zA-Z0-9ñ]+)?_id$
Ejemplos
- user_id
- taxonomy_child_id
- taxonomy_parent_id
Validacion de los esquemas de base de datos
El objetivo de esta libreria es proporcionar validaciones para los esquemas de la base de datos y para ello se utilizaran las siguientes estructuras:
ValidationAlgorithm
Proporciona la interfaz estrategia que es común a todas las estrategias concretas para la generacion de las validaciones de la base de datos
VerificationNonAdditiveConcatenation
Encapsula el Algoritmo 11.1 de Verificación de la propiedad de concatenación no aditiva propuesto por RAMEZ ELMASRI y SHAMKANT B. NAVATHE
VerificationBCNF
Encapsula el Algoritmo que valida que cada descomposicion posea la BCNF en base a la definicion presentada por RAMEZ ELMASRI y SHAMKANT B. NAVATHE
Para el algoritmo se utilizar el conjunto de dependencias funcionales no triviales en el que tanto el antecedente como el consecuente son subconjuntos del conjunto de atributos de la descomposición, en lugar de utilizar el conjunto de dependencias no triviales en la proyección del conjunto de dependencias funcionales para esa descomposición esto debido a que para fines del algoritmo para verificar la BCNF los conjuntos funcionan de forma equivalente.
La demostracion formal de dicha afirmacion se encuentra en el README.md del paquete database-auditor.
Uso
Requisitos
Instalacion
Como usuario
composer install israeldavidvm/database-auditor
composer global require israeldavidvm/database-auditor
composer require israeldavidvm/database-auditor
Como biblioteca (Solo si quieres crear un programa que use la libreria)
composer require israeldavidvm/database-auditor
Archivo .env (esto es necesario cuando se quiere generar un esquema a partir de ña base de datos el comportamiento por defecto)
Establece una configuracion en el archivo .env. como la siguiente
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=<DatabaseName>
DB_USERNAME=<UserName>
DB_PASSWORD=<password>
Uso desde la interfaz de linea de comandos
Para poder usar el programa solo necesitaras un archivo .env con la configuracion de tu base de datos como se especifico anteriormente y ejecutar el comando
Si es incluido en un proyecto por medio de require con el global (composer global require israeldavidvm/database-auditor)
~/.config/composer/vendor/bin/database-auditor app:audit-database [<validationAlgorithms> [<databaseSchemaGeneratorConfig>]]
Si es incluido en un proyecto por medio de require sin el global (composer require israeldavidvm/database-auditor)
./vendor/bin/database-auditor app:audit-database [<validationAlgorithms> [<databaseSchemaGeneratorConfig>]]
Si es instalado por medio de install o se parte de la raiz del proyecto (composer install israeldavidvm/database-auditor)
composer audit-database [<validationAlgorithms> [<databaseSchemaGeneratorConfig>]]
Description: Este comando te permite realizar una serie de validacionesen tu base de datos redirige la salida para pasar la informacion a un archivo
Arguments: validationAlgorithms Valor de los tipos de algoritmo de validacion a aplicar separados por coma (,) Ejemplo VerificationBCNF,VerificationNonAdditiveConcatenation [default: "VerificationBCNF,VerificationNonAdditiveConcatenation"] databaseSchemaGeneratorConfig Cadena que especifica el databaseSchemaGenerator y su configuracionDonde la cadena tiene un formato como el siguiente|Donde es el Valor del tipo de generador de esquema de base de datoscomo por ejemplo SchemaFromDatabaseUsingNamey es la configuracion del generador de esquema de base de datos que depemndera del tipo para el caso de SchemaFromDatabaseUsingName tiene el formato || [default: "SchemaFromDatabaseUsingName|exclude|users,migrations,password_resets,failed_jobs,personal_access_tokens,taxonomy_taxonomy|./.env"]
Options: -h, --help Display help for the given command. When no command is given display help for the list command --silent Do not output any message -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug