Skip to content

Commit

Permalink
Merge pull request #287 from rpbouman/dev
Browse files Browse the repository at this point in the history
new version
  • Loading branch information
rpbouman authored Dec 10, 2024
2 parents c9814d5 + 87c4c84 commit 3bc8659
Show file tree
Hide file tree
Showing 17 changed files with 835 additions and 512 deletions.
12 changes: 12 additions & 0 deletions src/App/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ main.layout {
gap: 0px;
}

main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) {
cursor: wait;
}

html > body[aria-busy=true] > main#layout {
display: none;
}

html > body[aria-busy=false] > #spinner {
display: none;
}

nav#sidebar {
width: 350px;
height: calc(100vh - 40px);
Expand Down
10 changes: 2 additions & 8 deletions src/App/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,14 @@ function initDuckdbVersion(){
return `${key} AS ${getQuotedIdentifier(columns[key])}`;
}).join('\n,');
var sql = `SELECT ${selectListSql}`
connection.query(sql)
var result = connection.query(sql)
.then(function(resultset){
var duckdbVersionLabel = byId('duckdbVersionLabel');
var row = resultset.get(0);
var version = row[versionColumn];
var api = row[apiColumn];
duckdbVersionLabel.innerText = `DuckDB ${version}, API: ${api}`;

var spinner = byId('spinner');
if (spinner){
spinner.style.display = 'none';
}
var layout = byId('layout');
layout.style.display = '';
document.body.setAttribute('aria-busy', false);
})
.catch(function(){
console.error(`Error fetching duckdb version info.`);
Expand Down
41 changes: 21 additions & 20 deletions src/AttributeUi/AttributeUi.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side

.attributeUi {
user-select: none;
details[role=treeitem][data-nodetype='aggregate'] > summary,

details[role=treeitem][data-nodetype='aggregate'] > summary,
details[data-nodetype='derived']:not( [data-derivation='elements'] ) > summary {
list-style: none;
margin-left: 16px;
}

details[role=treeitem] {

> summary {
white-space: nowrap;

> span.label {
max-width: calc(100% - 166px);
width: 100%;
Expand All @@ -32,7 +32,7 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side
width: 24px;
padding: 6px 3px 0px 3px;
text-align: center;

}

/**
Expand All @@ -58,20 +58,21 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side
.attributeUiAxisButton > input[type=checkbox] {
display: none;
}



> .attributeUiAxisButton[data-axis=rows]::before {
/* table-column */
/*
It may seem backward that we're using the table-column icon for the rows axis,
/*
It may seem backward that we're using the table-column icon for the rows axis,
but because the icon shows the highlighted first column, it matches the location of the row headers of a pivot table
*/
content: "\faff";
}

> .attributeUiAxisButton[data-axis=columns]::before {
/* table-row */
/*
It may seem backward that we're using the table-row icon for the columns axis,
/*
It may seem backward that we're using the table-row icon for the columns axis,
but because the icon shows the highlighted first row, it matches the location of the column headers of a pivot table
*/
content: "\fb00";
Expand All @@ -85,7 +86,7 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side
> span.attributeUiAxisButton {
visibility:hidden;
}

> .attributeUiAxisButton:has( > input[type=checkbox]:checked ) {
color: var( --huey-icon-color-highlight );
}
Expand All @@ -96,28 +97,28 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side
/* filter */
content: "\eaa5";
}

> .attributeUiAxisButton[data-axis=filters]:has( > input[type=checkbox]:checked )::before {
/* filter-x */
/* content: "\fa04"; */
/* filter-off */
content: "\ed2c";
}

}

> summary:hover > span.label::before {
color: var( --huey-icon-color-highlight );
}

/**
* folder icons
*/
[data-nodetype=folder] > summary > span.label::before {
/* folder */
content: "\eaad";
}

[data-nodetype=folder][open] > summary > span.label::before {
/* folder-open */
content: "\faf7";
Expand Down Expand Up @@ -421,7 +422,7 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side
/**
*
* https://github.com/rpbouman/huey/issues/223: highlight labels of attribute ui nodes that somehow contribute to the query.
*
*
*/
details > summary:has( > label > input[type=checkbox]:checked ) > span.label,
details:has( details > summary > label > input[type=checkbox]:checked ) > summary > span.label {
Expand All @@ -433,5 +434,5 @@ main.layout:has( .workarea > .pivotTableUiContainer[aria-busy=true] ) > nav#side
color: var( --huey-icon-color-highlight );
font-weight: normal;
}

}
144 changes: 142 additions & 2 deletions src/DataSet/CellSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class CellSet extends DataSetComponent {
#getDataFoundationCteSql(
cellsAxisItemsToFetch
){
var alias = CellSet.datasetRelationName;
var alias = CellSet.datasetRelationName
var tupleSets = this.#tupleSets;

var selectListExpressions = {};
Expand Down Expand Up @@ -366,6 +366,67 @@ class CellSet extends DataSetComponent {
return queries.join('\nUNION ALL\n');
}

#getTuplesCte(tuplesToQuery, tuplesFields, includeGroupingId){
var tupleSets = this.#tupleSets;
var totalsItems = [];
var combinationTuples = [];
var allQueryAxisItems = [];
var cellIndices = Object.keys(tuplesToQuery);
_cells: for (var i = 0; i < cellIndices.length; i++) {
var groupingId = 0;
var cellIndex = cellIndices[i];
var combinationTuple = [cellIndex];
var tuples = tuplesToQuery[cellIndex];
_tuples: for (var j = 0; j < tuples.length; j++){
var tupleSet = tupleSets[j];
var queryAxisItems = tupleSet.getQueryAxisItems();
if (i === 0) {
allQueryAxisItems = allQueryAxisItems.concat(queryAxisItems);
totalsItems[j] = queryAxisItems.filter(function(queryAxisItem){
return queryAxisItem.includeTotals;
});
}
if (j){
groupingId <<= totalsItems[j-1].length;
}
var tuple = tuples[j];
if (tuple){
groupingId += parseInt(tuple[TupleSet.groupingIdAlias]) || 0;
var tupleValues = tuple.values;
var fields = tuplesFields[j];
_fields: for (var k = 0; k < queryAxisItems.length; k++){
var queryAxisItem = queryAxisItems[k];
var tupleValue = tupleValues[k];
var tupleValueField = fields[k];
var literal = queryAxisItem.literalWriter ? queryAxisItem.literalWriter(tupleValue, tupleValueField) : String(tupleValue);
combinationTuple.push(literal);
}
}
}
if (includeGroupingId) {
combinationTuple.push(groupingId);
}
combinationTuples.push(combinationTuple);
}
if (cellIndices.length === 0){
combinationTuples.push([0]);
}
var tuplesSql = combinationTuples.map(function(combinationTuple){
return `(${combinationTuple.join(',')})`;
}).join('\n , ');

var relationDefinition = allQueryAxisItems.map(function(queryAxisItem){
return getQuotedIdentifier( QueryAxisItem.getCaptionForQueryAxisItem(queryAxisItem) );
});
relationDefinition.unshift(getQuotedIdentifier(CellSet.#cellIndexColumnName));
if (includeGroupingId) {
relationDefinition.push(getQuotedIdentifier(TupleSet.groupingIdAlias));
}
relationDefinition = `${getQuotedIdentifier(CellSet.#tupleDataRelationName)}(\n ${relationDefinition.join('\n, ')}\n)`;
tuplesSql = `${relationDefinition} AS (\n FROM (VALUES\n ${tuplesSql}\n )\n)`;
return tuplesSql;
}

#getSqlQueryForCells(
// object keyed by cellindex, with an array of tuples as value.
tuplesToQuery,
Expand All @@ -377,18 +438,97 @@ class CellSet extends DataSetComponent {
var queryModel = this.getQueryModel();
var datasource = queryModel.getDatasource();

var rowsAxisItems = queryModel.getRowsAxis().getItems();
var columnsAxisItems = queryModel.getColumnsAxis().getItems();
var axisItems = [].concat(rowsAxisItems, columnsAxisItems);
var allItems = [].concat(axisItems, cellsAxisItemsToFetch || []);
var sql = SqlQueryGenerator.getSqlSelectStatementForAxisItems({
datasource: queryModel.getDatasource(),
queryAxisItems: allItems,
filterAxisItems: queryModel.getFiltersAxis().getItems(),
includeOrderBy: false,
finalStateAsCte: true,
cteName: '__huey_cells'
});

var totalsItems = allItems.filter(function(queryAxisItem){
return queryAxisItem.includeTotals === true;
});
var hasTotalsItems = Boolean(totalsItems.length);
var tuples = this.#getTuplesCte(tuplesToQuery, tuplesFields, hasTotalsItems);

sql += `\n, ${tuples}`;

var select = cellsAxisItemsToFetch.map(function(axisItem){
var expression = QueryAxisItem.getCaptionForQueryAxisItem(axisItem);
var qualifiedIdentifier = getQualifiedIdentifier('__huey_cells', expression);
var alias = QueryAxisItem.getSqlForQueryAxisItem(axisItem, CellSet.datasetRelationName);
return `${qualifiedIdentifier} AS ${getQuotedIdentifier(alias)}`;
});
select.unshift(
getQualifiedIdentifier(
CellSet.#tupleDataRelationName,
CellSet.#cellIndexColumnName
)
);
var from = `FROM ${getQuotedIdentifier(CellSet.#tupleDataRelationName)}`;
var joinSql, onCondition;
if (axisItems.length) {
joinSql = `LEFT JOIN`;
onCondition = axisItems.map(function(axisItem){
var axisExpression = QueryAxisItem.getCaptionForQueryAxisItem(axisItem)
var leftExpression = getQualifiedIdentifier(CellSet.#tupleDataRelationName, axisExpression);
var rightExpression = getQualifiedIdentifier('__huey_cells', axisExpression);
return `${leftExpression} is not distinct from ${rightExpression}`;
});
}
else {
joinSql = `CROSS JOIN`;
onCondition = '';
}
joinSql += ` ${getQuotedIdentifier('__huey_cells')}`;
from += `\n${joinSql}`;

if (hasTotalsItems) {
select.push(
getQualifiedIdentifier(
CellSet.#tupleDataRelationName,
TupleSet.groupingIdAlias
)
);
var leftExpression = getQualifiedIdentifier(CellSet.#tupleDataRelationName, TupleSet.groupingIdAlias);
var rightExpression = getQualifiedIdentifier('__huey_cells', TupleSet.groupingIdAlias);
onCondition.push(`${leftExpression} = ${rightExpression}`);
}

if (onCondition.length) {
from += `\nON ${onCondition.join(`\nAND `)}`;
}

sql += `\nSELECT ${select.join('\n, ')}`;
sql += `\n${from}`;

/*
console.log('experimental');
console.log(sql);
var dataFoundationCteSql = this.#getDataFoundationCteSql(cellsAxisItemsToFetch);
var tupleDataCtes = this.#getTupleDataCteSql(
tuplesToQuery,
tuplesFields,
cellsAxisItemsToFetch
);
var sql = [
var oldSql = [
`WITH ${dataFoundationCteSql}`,
tupleDataCtes
].join('\n');
console.log('oldSql:');
console.log(oldSql);
*/
return sql;

}

async #executeCellsQuery(
Expand Down
Loading

0 comments on commit 3bc8659

Please sign in to comment.