Skip to content

Commit

Permalink
Merge edaquery2 into SDA#53
Browse files Browse the repository at this point in the history
# Conflicts:
#	.gitignore
#	eda/eda_api/lib/module/dashboard/dashboard.controller.ts
#	eda/eda_api/lib/module/datasource/datasource.controller.ts
#	eda/eda_api/lib/module/updateModel/updateModel.controller.ts
#	eda/eda_api/lib/router.ts
#	eda/eda_api/lib/services/query-builder/query-builder.service.ts
#	eda/eda_app/src/app/module/components/eda-kpi/eda-kpi.component.html
#	eda/eda_app/src/app/module/components/eda-table/eda-table.ts
#	eda/eda_app/src/app/module/pages/about/about.component.css
#	eda/eda_app/src/app/module/pages/about/about.component.html
#	eda/eda_app/src/app/module/pages/dashboard/dashboard.component.ts
#	eda/eda_app/src/app/module/pages/pages.module.ts
#	eda/eda_app/src/app/shared/components/sidebar/sidebar.component.html
#	eda/eda_app/src/assets/sass/eda-styles/components/sidebar-style.css
#	eda/eda_app/src/locale/messages.ca.xlf
#	eda/eda_app/src/locale/messages.en.xlf
#	eda/eda_app/src/locale/messages.es.xlf
#	eda/eda_app/src/locale/messages.gl.xlf
#	eda/eda_app/src/locale/messages.pl.xlf
#	eda/eda_app/src/locale/stic_messages.ca.xlf
#	eda/eda_app/src/locale/stic_messages.en.xlf
#	eda/eda_app/src/locale/stic_messages.es.xlf
#	eda/eda_app/src/locale/stic_messages.gl.xlf
  • Loading branch information
Juanjo Ortilles authored and Juanjo Ortilles committed Apr 8, 2024
2 parents 5d7c3c9 + b6a62ee commit 636dcdf
Show file tree
Hide file tree
Showing 37 changed files with 2,951 additions and 1,422 deletions.
2 changes: 1 addition & 1 deletion eda/eda_api/lib/module/dashboard/dashboard.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ export class DashboardController {
if (
isNaN(val) || val.toString().indexOf('-') >= 0 || val.toString().indexOf('/') >= 0 ||
val.toString().indexOf('|') >= 0 || val.toString().indexOf(':') >= 0 || val.toString().indexOf('T') >= 0 ||
val.toString().indexOf('Z') >= 0 || val.toString().indexOf('Z') >= 0) {
val.toString().indexOf('Z') >= 0 || val.toString().indexOf('Z') >= 0 || val.toString().replace(/['"]+/g, '').length == 0 ) {
isNotNumeric = true;
}
} catch (e) {
Expand Down
265 changes: 223 additions & 42 deletions eda/eda_api/lib/services/query-builder/query-builder.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as _ from 'lodash';

class TreeNode {
public value: string;
public child: Array<TreeNode>
Expand Down Expand Up @@ -48,7 +47,7 @@ export abstract class QueryBuilderService {

let graph = this.buildGraph();
/* Agafem els noms de les taules, origen i destí (és arbitrari), les columnes i el tipus d'agregació per construïr la consulta */
let origin = this.queryTODO.fields.find(x => x.order === 0).table_id;
let origin = this.queryTODO.rootTable || this.queryTODO.fields.find(x => x.order === 0).table_id;
let dest = [];
const valueListList = [];
const modelPermissions = this.dataModel.ds.metadata.model_granted_roles;
Expand All @@ -63,9 +62,21 @@ export abstract class QueryBuilderService {
this.permissions = [];
}
/** joins per els value list */
const valueListJoins = [];
let valueListJoins = [];


/** Reviso si cap columna de la consulta es un multivalueliest..... */
/** ............................................................................... */
/** ............................PER ELS VALUE LISTS................................ */
/** si es una consulta de llista de valors es retorna la llista de valors possibles */
/** ............................................................................... */
/*
if( this.queryTODO.fields.length == 1 && this.queryTODO.fields[0].valueListSource && this.queryTODO.fields[0].column_type === 'text' && this.permissions.length == 0&& this.queryTODO.filters.length == 0){
nO APLICA PORQUE NO APLICA LA SEGURDAD
this.query = this.valueListQuery( );
return this.query;
}
*/
/** Reviso si cap columna de la consulta es un multivalueliest..... */
this.queryTODO.fields.forEach( e=>{
if( e.valueListSource ){
valueListList.push( JSON.parse(JSON.stringify(e)) );
Expand Down Expand Up @@ -111,7 +122,6 @@ export abstract class QueryBuilderService {
});
}


/** ..........................PER ELS VALUE LISTS................................ */


Expand All @@ -133,53 +143,106 @@ export abstract class QueryBuilderService {
}



/** SEPAREM ENTRE AGGREGATION COLUMNS/GROUPING COLUMNS */
const separedCols = this.getSeparedColumns(origin, dest);
const columns = separedCols[0];
const grouping = separedCols[1];


let joinTree = [];
let tree = [];
for (const query of this.queryTODO.fields) {
if (query.joins && query.joins.length > 0) {
for (const join of query.joins) {
tree.push(join);
}
}
}

for (const filter of this.queryTODO.filters) {
if (filter.joins && filter.joins.length > 0) {
for (const join of filter.joins) {
tree.push(join);
}
}
}

// console.log(JSON.stringify( [...new Set(tree)] ));

// Las taules de les consultes van primer per potenciar relacions directes
const vals = [...dest];
const firs = [];
vals.forEach(v => firs.push( graph.filter( e => v == e.name )[0]) );
firs.forEach(e => graph = graph.filter(f=> f.name != e.name) );
graph = [...firs, ...graph];


/** ARBRE DELS JOINS A FER */
let joinTree = this.dijkstraAlgorithm(graph, origin, dest.slice(0));
// Busco relacions directes.
if( ! this.validateJoinTree( joinTree, dest ) ){
let exito = false;
let new_origin = '';
let new_dest = [...dest];
let new_joinTree:any;
for (let d of dest) {
new_origin = d;
new_dest = [...dest].filter(e => e !== d);
new_dest.push(origin);
new_joinTree = this.dijkstraAlgorithm(graph, new_origin, new_dest.slice(0) );
if( this.validateJoinTree( new_joinTree, new_dest ) ){
exito = true;
break;
if (tree.length === 0) {
/** ARBRE DELS JOINS A FER */
joinTree = this.dijkstraAlgorithm(graph, origin, dest.slice(0));
// Busco relacions directes.
if( ! this.validateJoinTree( joinTree, dest ) ){
let exito = false;
let new_origin = '';
let new_dest = [...dest];
let new_joinTree:any;
for (let d of dest) {
new_origin = d;
new_dest = [...dest].filter(e => e !== d);
new_dest.push(origin);
new_joinTree = this.dijkstraAlgorithm(graph, new_origin, new_dest.slice(0) );
if( this.validateJoinTree( new_joinTree, new_dest ) ){
exito = true;
break;
}
}
if(exito){
origin = new_origin;
dest = [...new_dest];
joinTree = new_joinTree;
}
}
if(exito){
origin = new_origin;
dest = [...new_dest];
joinTree = new_joinTree;
}
}

/**poso les taules de la consulta al principi del joinTree per potenciar relacions directes */
const my_tables = [...dest ];
const firsts = [];
my_tables.forEach( e => firsts.push( joinTree.filter( t => e == t.name )[0]) );
firsts.forEach(e => joinTree = joinTree.filter(f=> f.name != e.name) );
joinTree = [...firsts, ...joinTree];

this.queryTODO.joined = false;
/**poso les taules de la consulta al principi del joinTree per potenciar relacions directes */
const my_tables = [...dest ];
const firsts = [];
my_tables.forEach( e => firsts.push( joinTree.filter( t => e == t.name )[0]) );
firsts.forEach(e => joinTree = joinTree.filter(f=> f.name != e.name) );
joinTree = [...firsts, ...joinTree];

} else {
valueListJoins = [];

for (const field of this.queryTODO.fields) {
if(field.valueListSource) {
valueListJoins.push(field.valueListSource);
}
}

for (const value of valueListJoins) {
const multiSourceJoin = `${value.source_table}.${value.source_column}`;
const multiTargetJoin = `${value.target_table}.${value.target_id_column}`;

let exists = false;
for (const join of tree) {
const sourceJoin = join[0];
const targetJoin = join[1];

if (multiSourceJoin == sourceJoin && multiTargetJoin == targetJoin) {
exists = true;
}
}

if (!exists) {
tree.push([multiSourceJoin, multiTargetJoin]);
}
}
valueListJoins = [...new Set(valueListJoins.map((value) => value.target_table))];
tree = [...new Set(tree)];
joinTree = tree;
this.queryTODO.joined = true;
}

//to WHERE CLAUSE
const filters = this.queryTODO.filters.filter(f => {
Expand Down Expand Up @@ -245,7 +308,111 @@ export abstract class QueryBuilderService {
}


public getGraph(graph, origin, dest) {
let new_origin = origin;
const workingGrapth = JSON.parse(JSON.stringify(graph));
//inicializo en el origen.
let elem = workingGrapth.filter(e => e.name === new_origin )[0];
const ruta = { name: elem.name, paths: [] };
elem.rel.forEach((r,i) => {
ruta.paths[i]=[];
ruta.paths[i].push(elem.name);
ruta.paths[i].push(r);
});

let index = workingGrapth.indexOf(workingGrapth.find(x => x.name === elem.name));
if (index > -1) {
workingGrapth.splice(index, 1);
}
let exito = 0;
let grow = 0;
while(exito == 0){
ruta.paths.forEach((p,i) => {
grow = 0;
new_origin = p[p.length-1];
elem = workingGrapth.filter(e => e.name === new_origin )[0];
if(elem.rel.length > 1 ){
elem.rel.forEach(
e=>{ console.log( e); console.log(ruta.paths[i]);
const currentLenght = ruta.paths[i].length;
let dup = [...ruta.paths[i]];
dup.push(e);
let unique = new Set(dup);
dup = [...unique];
const newLenght = dup.length;
if( newLenght > currentLenght){
console.log('Crece');
console.log( 'Tamaños: ' + currentLenght + ' - ' + newLenght );
console.log(ruta.paths[i]);
console.log(dup);
grow = 1;
}
ruta.paths.push( dup );
}
)
ruta.paths.splice(i,1);
}else{
if(ruta.paths.length-1 == i){ exito = 1; }
}
});
if(grow == 0){
exito = 1;
}

}


//console.log('rutas posibles ==================');
//console.log(ruta.paths);
//console.log('rutas==================');




const goodPaths = [];
let finalPaths = [];

ruta.paths.forEach( r => {
var exito = 1;
finalPaths.forEach(f=>{ if( this.arrayEquals(r,f) ){exito = 0; } });
if(exito == 1){
finalPaths.push(r);
}
})
// rutas limpias sin duplicados.
ruta.paths = [...finalPaths];
finalPaths = [];

ruta.paths.forEach( r => {
let exito = 1;
dest.forEach(e => { if(r.indexOf(e)<0){ exito=0;}} );
if( exito==1){goodPaths.push(r);}
})
//Si tengo un origen y un destino.
goodPaths.forEach((p,i)=>{
if( dest.indexOf( p[p.length-1] ) >=0 ){ finalPaths.push(p);}
})




console.log('Rutas finales:');
console.log(finalPaths);
ruta.paths = finalPaths;
// { name: 'orders', dist: Infinity, path: [] }

}


public arrayEquals(a, b) {
return Array.isArray(a) &&
Array.isArray(b) &&
a.length === b.length &&
a.every((val, index) => val === b[index]);
}

public dijkstraAlgorithm(graph, origin, dest) {
// this.getGraph(graph, origin, dest);
const not_visited = [];
const v = [];

Expand Down Expand Up @@ -294,6 +461,8 @@ export abstract class QueryBuilderService {
})

}
//console.log('disgtra devuelve: ');
//console.log(v)
return (v);
}

Expand Down Expand Up @@ -427,14 +596,14 @@ export abstract class QueryBuilderService {


public findColumn(table: string, column: string) {
const tmpTable = this.tables.find(t => t.table_name === table);
const col = tmpTable.columns.find(c => c.column_name === column);
col.table_id = tmpTable.table_name;
const tmpTable = this.tables.find((t: any) => t.table_name === table.split('.')[0]);
const col = tmpTable.columns.find((c: any) => c.column_name === column);
col.table_id = table;
return col;
}

public findHavingColumn(table: string, column: string) {
return this.queryTODO.fields.find(f=> f.table_id === table && f.column_name === column);
return this.queryTODO.fields.find((f: any)=> f.table_id === table.split('.')[0] && f.column_name === column);
}

public setFilterType(filter: string) {
Expand Down Expand Up @@ -771,11 +940,23 @@ export abstract class QueryBuilderService {

equalfilters.map.forEach((value, key) => {
let filterSTR = '\nand ('
value.forEach(f => {
filterSTR += this.filterToString(f) + '\n or ';

//poso els nulls al principi
let n = value.filter( f=> f.filter_type == 'not_null');
let values = [...n, ...value.filter( f=> f.filter_type != 'not_null')];

values.forEach(f => {
if(f.filter_type == 'not_null'){
//Fins que no es pugi determinar el tipus de conjunció. Els filtres sobre una mateixa columna es un or perque vull dos grups. EXCEPTE QUAN ES UN NULL
filterSTR += this.filterToString(f ) + '\n and ';
}else{
filterSTR += this.filterToString(f ) + '\n or ';
}


});

filterSTR = filterSTR.slice(0, -3);
filterSTR = filterSTR.slice(0, -4);
filterSTR += ') ';
filtersString += filterSTR;
});
Expand Down
3 changes: 1 addition & 2 deletions eda/eda_api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "api-eda",
"version": "0.1.0",
"version": "2.0.0",
"description": "",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -34,7 +34,6 @@
"express-method-override": "0.0.3",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"mariadb": "^3.1.2",
"mongoose": "^5.13.15",
"mongoose-unique-validator": "^2.0.3",
"mssql": "^8.0.2",
Expand Down
Loading

0 comments on commit 636dcdf

Please sign in to comment.