BCJR implementation
WDM code added (Pol Cont., Opt MUX/DEMUX, Opt Atten, DP_Fiber) -> the codebase is not optimized to always work with dp signals!
This commit is contained in:
@@ -63,7 +63,9 @@ classdef DBHandler < handle
|
||||
obj.refresh();
|
||||
|
||||
else
|
||||
|
||||
error('DB seems to be corrupt')
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -183,6 +185,7 @@ classdef DBHandler < handle
|
||||
fprintf('Raw Rx Paths: Found %d duplictaes of %s \n',duplictae_raw.occurrences(i),duplictae_raw.rx_raw_path(i));
|
||||
end
|
||||
end
|
||||
|
||||
healthyDB = true;
|
||||
end
|
||||
|
||||
@@ -713,68 +716,167 @@ classdef DBHandler < handle
|
||||
selectedFields
|
||||
end
|
||||
|
||||
% Step 1: Handle selectedFields conversion
|
||||
% -------- Step 1: Normalize selectedFields to {'Table.field', ...} --------
|
||||
if isempty(selectedFields) || (ischar(selectedFields) && strcmpi(selectedFields, 'all'))
|
||||
selectedFields = obj.getTableFieldNames('Runs'); % Default to Runs table
|
||||
selectedFields = obj.getTableFieldNames('Runs'); % default
|
||||
elseif isstruct(selectedFields)
|
||||
% Convert struct to cell array of 'Table.field' format
|
||||
newFields = {};
|
||||
tableNames = fieldnames(selectedFields);
|
||||
for t = 1:numel(tableNames)
|
||||
tableStruct = selectedFields.(tableNames{t});
|
||||
fieldNames = fieldnames(tableStruct);
|
||||
for f = 1:numel(fieldNames)
|
||||
if isequal(tableStruct.(fieldNames{f}), 1)
|
||||
newFields{end+1} = sprintf('%s.%s', tableNames{t}, fieldNames{f});
|
||||
fns = fieldnames(tableStruct);
|
||||
for f = 1:numel(fns)
|
||||
if isequal(tableStruct.(fns{f}), 1)
|
||||
newFields{end+1} = sprintf('%s.%s', tableNames{t}, fns{f}); %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
end
|
||||
selectedFields = newFields;
|
||||
end
|
||||
|
||||
% Step 2: Generate COALESCE string for SELECT clause
|
||||
% Parse the table names actually referenced by the SELECT
|
||||
reqTables = unique(cellfun(@(s) extractBefore(s, '.'), selectedFields, ...
|
||||
'UniformOutput', false));
|
||||
|
||||
% -------- Step 2: Build SELECT with COALESCE wrapper as you already do ----
|
||||
selectClause = obj.generateCoalesceString(selectedFields);
|
||||
|
||||
% Step 3: Generate FROM clause with joins
|
||||
mainTable = 'Runs';
|
||||
fromClause = ['FROM ', mainTable, ' '];
|
||||
% -------- Step 3: FROM and minimal JOIN plan ------------------------------
|
||||
% Decide main table: prefer the first explicitly referenced table, else 'Runs'
|
||||
if ~isempty(reqTables)
|
||||
mainTable = reqTables{1};
|
||||
else
|
||||
mainTable = 'Runs';
|
||||
end
|
||||
|
||||
% Prepare join buffers
|
||||
normalJoins = '';
|
||||
equalizerJoin = '';
|
||||
|
||||
tableNamesAll = fieldnames(obj.tables);
|
||||
for t = 1:numel(tableNamesAll)
|
||||
tableName = tableNamesAll{t};
|
||||
|
||||
if strcmpi(tableName, mainTable) || strcmpi(tableName, 'sqlite_sequence')
|
||||
continue;
|
||||
end
|
||||
|
||||
if isfield(obj.tables.(tableName), 'run_id')
|
||||
% Direct join to Runs
|
||||
normalJoins = [normalJoins, 'LEFT JOIN ', tableName, ...
|
||||
' ON ', mainTable, '.run_id = ', tableName, '.run_id '];
|
||||
elseif isfield(obj.tables.(tableName), 'eq_id')
|
||||
% Equalizer depends on Results, collect this join separately
|
||||
equalizerJoin = ['LEFT JOIN ', tableName, ...
|
||||
' ON Results.eq_id = ', tableName, '.eq_id '];
|
||||
% If WHERE references a table not in reqTables (e.g., Runs.*), make sure it’s present.
|
||||
whereClause = '';
|
||||
if ~isempty(filterParams)
|
||||
whereClause = obj.generateWhereClause(filterParams);
|
||||
% Heuristic: add 'Runs' if WHERE clause mentions 'Runs.'
|
||||
if contains(whereClause, 'Runs.')
|
||||
reqTables = unique([reqTables; {'Runs'}]); %#ok<AGROW>
|
||||
end
|
||||
end
|
||||
|
||||
% Combine joins: normal joins first, Equalizer last
|
||||
fromClause = [fromClause, normalJoins, equalizerJoin];
|
||||
% Ensure main table is included
|
||||
if ~ismember(mainTable, reqTables)
|
||||
reqTables = unique([mainTable; reqTables]); %#ok<AGROW>
|
||||
end
|
||||
|
||||
% Step 4: Generate WHERE clause if filter parameters exist
|
||||
if ~isempty(filterParams)
|
||||
whereClause = obj.generateWhereClause(filterParams);
|
||||
if ~isempty(whereClause)
|
||||
query = [selectClause, ' ', fromClause, 'WHERE ', whereClause];
|
||||
else
|
||||
query = [selectClause, ' ', fromClause];
|
||||
% We’ll build joins only for the required tables (minus the main)
|
||||
otherTables = setdiff(reqTables, {mainTable});
|
||||
|
||||
% Keep track of what’s already in the FROM graph (start with main)
|
||||
present = string(mainTable);
|
||||
joins = strings(0,1);
|
||||
|
||||
% Helper lambdas
|
||||
hasField = @(tbl, fld) isfield(obj.tables.(char(tbl)), char(fld));
|
||||
canJoinBy = @(left, right, key) hasField(left, key) && hasField(right, key);
|
||||
|
||||
|
||||
% A small helper that adds a LEFT JOIN if the right table isn't present yet
|
||||
function addJoinByKey(rightTbl, key)
|
||||
if any(present == string(rightTbl))
|
||||
return; % already joined
|
||||
end
|
||||
% Prefer to join against an already-present table that has the key
|
||||
anchor = '';
|
||||
for k = 1:numel(present)
|
||||
if canJoinBy(char(present(k)), rightTbl, key)
|
||||
anchor = char(present(k));
|
||||
break;
|
||||
end
|
||||
end
|
||||
if isempty(anchor)
|
||||
% No anchor in current graph; if the right table is 'Equalizer' and key is eq_id,
|
||||
% try to ensure a bridge table with eq_id exists (Results or a dashboard view).
|
||||
if strcmpi(rightTbl,'Equalizer') && strcmpi(key,'eq_id')
|
||||
% Bring in one eq_id-capable table if it is requested
|
||||
bridgeOrder = {'Results','dashboard_old','dashboard_new','dashboard_ungrouped'};
|
||||
for b = 1:numel(bridgeOrder)
|
||||
br = bridgeOrder{b};
|
||||
if ismember(br, reqTables) && ~any(present == string(br)) && hasField(obj.tables.(br),'eq_id')
|
||||
% Attach bridge by run_id if possible, otherwise leave for eq_id
|
||||
if any(present == "Runs") && hasField(obj.tables.(br),'run_id') && hasField(obj.tables.('Runs'),'run_id')
|
||||
joins(end+1,1) = "LEFT JOIN " + br + " ON Runs.run_id = " + br + ".run_id";
|
||||
present(end+1,1) = string(br);
|
||||
anchor = br; % we can now anchor Equalizer on eq_id to this
|
||||
break;
|
||||
else
|
||||
% Fallback: anchor to main if it shares eq_id
|
||||
for k = 1:numel(present)
|
||||
pk = char(present(k));
|
||||
if canJoinBy(pk, br, 'eq_id')
|
||||
joins(end+1,1) = "LEFT JOIN " + br + " ON " + pk + ".eq_id = " + br + ".eq_id";
|
||||
present(end+1,1) = string(br);
|
||||
anchor = br;
|
||||
break;
|
||||
end
|
||||
end
|
||||
if ~isempty(anchor), break; end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
% Re-scan for an anchor (maybe the bridge helped)
|
||||
if isempty(anchor)
|
||||
for k = 1:numel(present)
|
||||
if canJoinBy(char(present(k)), rightTbl, key)
|
||||
anchor = char(present(k));
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
if isempty(anchor)
|
||||
% As a final fallback, if the main table is Runs and right has run_id, join by run_id
|
||||
if strcmpi(mainTable,'Runs') && hasField(obj.tables.(rightTbl),'run_id') && hasField(obj.tables.('Runs'),'run_id')
|
||||
anchor = 'Runs';
|
||||
key = 'run_id';
|
||||
end
|
||||
end
|
||||
if isempty(anchor)
|
||||
% Could not find a path; skip join silently (or throw if you prefer strict)
|
||||
return;
|
||||
end
|
||||
joins(end+1,1) = "LEFT JOIN " + rightTbl + " ON " + anchor + "." + key + " = " + rightTbl + "." + key;
|
||||
present(end+1,1) = string(rightTbl);
|
||||
end
|
||||
|
||||
% First pass: if WHERE uses Runs.* and mainTable isn’t Runs, ensure Runs is in the graph
|
||||
if contains(string(whereClause), "Runs.") && ~any(present == "Runs")
|
||||
% Try to join Runs to whatever has run_id (mainTable ideally)
|
||||
if hasField(mainTable, 'run_id') && hasField('Runs', 'run_id')
|
||||
joins(end+1,1) = "LEFT JOIN Runs ON " + string(mainTable) + ".run_id = Runs.run_id";
|
||||
present(end+1,1) = "Runs";
|
||||
end
|
||||
end
|
||||
|
||||
% Join the required tables with minimal edges
|
||||
for i = 1:numel(otherTables)
|
||||
tbl = otherTables{i};
|
||||
% Prefer run_id join if possible, else eq_id, else skip
|
||||
if any(present == "Runs") && hasField(tbl,'run_id')
|
||||
addJoinByKey(tbl, 'run_id');
|
||||
elseif hasField(tbl,'run_id') && hasField(mainTable,'run_id')
|
||||
addJoinByKey(tbl, 'run_id');
|
||||
elseif hasField(tbl,'eq_id')
|
||||
addJoinByKey(tbl, 'eq_id');
|
||||
else
|
||||
% no obvious key; skip
|
||||
end
|
||||
end
|
||||
|
||||
% Build the FROM clause
|
||||
fromClause = "FROM " + string(mainTable) + " " + strjoin(joins, " ");
|
||||
|
||||
% -------- Step 4: WHERE (unchanged logic) ------------------------------
|
||||
if ~isempty(whereClause)
|
||||
query = char(strjoin([selectClause, fromClause, "WHERE " + string(whereClause)], " "));
|
||||
else
|
||||
query = [selectClause, ' ', fromClause];
|
||||
query = char(strjoin([selectClause, fromClause], " "));
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user