Ejemplo n.º 1
0
 public static function selectReferencedColumnNames4ReferenceLink(array $linkExecutionStack, array $columnNames = NULL)
 {
     if (!isset($columnNames)) {
         return NULL;
     }
     $selectedColumnNames = NULL;
     $linkExecutionStackSize = count($linkExecutionStack);
     foreach ($columnNames as $columnName) {
         $columnNameReferences = ReferencePathHelper::splitReferencePath($columnName);
         $referenceSegmentCount = count($columnNameReferences);
         for ($referenceSegmentIndex = $referenceSegmentCount - 1, $stackPreviousIndex = -1; $referenceSegmentIndex >= 0; $referenceSegmentIndex--) {
             $reference = $columnNameReferences[$referenceSegmentIndex];
             list($referencedDatasetName, $referencedColumnName) = ReferencePathHelper::splitReference($reference);
             if (isset($referencedDatasetName)) {
                 // looking for related link in stack
                 $foundInStack = FALSE;
                 for ($stackIndex = $stackPreviousIndex + 1; $stackIndex < $linkExecutionStackSize && !$foundInStack; $stackIndex++) {
                     $stackLink = $linkExecutionStack[$stackIndex];
                     if ($referencedDatasetName != $stackLink->dataset->name) {
                         continue;
                     }
                     // checking parent column name
                     if ($stackIndex < $linkExecutionStackSize - 1 && $referenceSegmentIndex > 0) {
                         $nextStackLine = $linkExecutionStack[$stackIndex + 1];
                         // checking number of columns. It has to be single column
                         if (count($nextStackLine->parentColumnNames) > 1) {
                             break;
                         }
                         // checking if the parent column matches
                         if (array_search($referencedColumnName, $nextStackLine->parentColumnNames) === FALSE) {
                             break;
                         }
                     }
                     $stackPreviousIndex = $stackIndex;
                     $foundInStack = TRUE;
                 }
                 if (!$foundInStack) {
                     break;
                 }
                 // we did not reach end of the execution stack
                 if ($stackPreviousIndex < $linkExecutionStackSize - 1) {
                     continue;
                 }
             } else {
                 if ($linkExecutionStackSize > 1) {
                     // this column belongs to root link but we are working with nested link
                     break;
                 }
             }
             // original column name would be only the portion of the reference path
             $adjustedColumnName = ReferencePathHelper::assembleReferencePath(array_slice($columnNameReferences, $referenceSegmentIndex));
             $selectedColumnNames[$adjustedColumnName] = $referencedColumnName;
             break;
         }
     }
     return $selectedColumnNames;
 }
    protected function findColumnTableByReferencePath($referencePath) {
        $tableCount = count($this->tables);

        $references = ReferencePathHelper::splitReferencePath($referencePath);
        $references = array_reverse($references);

        $tableIndex = NULL;
        for ($i = 0, $refcount = count($references); $i < $refcount - 1; $i++) {
            $reference = $references[$i];
            list($referencedDatasetName, $referencedColumnName) = ReferencePathHelper::splitReference($reference);
            if (!isset($referencedDatasetName)) {
                continue;
            }

            $nextReference = $references[$i + 1];
            list($nextReferencedDatasetName, $nextReferencedColumnName) = ReferencePathHelper::splitReference($nextReference);
            if (!isset($nextReferencedDatasetName)) {
                continue;
            }

            $branchIndex = NULL;
            for ($j = (isset($tableIndex) ? $tableIndex : 0); $j < $tableCount; $j++) {
                $table = $this->tables[$j];
                if ($table->dataset->name == $referencedDatasetName) {
                    for ($k = $j + 1; $k < $tableCount; $k++) {
                        $nextTable = $this->tables[$k];
                        if (($nextTable->dataset->name == $nextReferencedDatasetName)
                                && ($nextTable->conditions[0]->joinValue->tableAlias == $table->alias)
                                && ($nextTable->conditions[0]->joinValue->columnName == $referencedColumnName)) {
                            $branchIndex = $k;
                            break 2;
                        }
                    }
                }
            }
            if (!isset($branchIndex)) {
                return NULL;
            }
            $tableIndex = $branchIndex;
        }

        return isset($tableIndex) ? $this->tables[$tableIndex] : NULL;
    }
    public function prepareStatementGenerationContext(AbstractCubeQueryRequest $request, CubeMetaData $cube) {
        $metamodel = data_controller_get_metamodel();

        $generationContext = new __DefaultQueryEngine_StatementGenerationContext();

        // checking if we use any non-additive measures in this request
        $foundNonAdditiveMeasure = FALSE;
        foreach ($cube->measures as $measure) {
            $measureName = $measure->name;
            $additivity = $measure->getAdditivity();

            if (($additivity == MeasureAdditivity::ADDITIVE) || ($additivity == MeasureAdditivity::SEMI_ADDITIVE)) {
                continue;
            }

            $selectedMeasure = $request->findMeasure($measureName);
            $queriedMeasure = $request->findMeasureQuery($measureName);
            if (!isset($selectedMeasure) && !isset($queriedMeasure)) {
                continue;
            }

            $foundNonAdditiveMeasure = TRUE;
            break;
        }

        // checking if only columns with non-unique values were requested for some dimensions
        if (isset($cube->dimensions)) {
            foreach ($cube->dimensions as $dimension) {
                $dimensionName = $dimension->name;

                $selectedDimension = $request->findDimension($dimensionName);
                $queriedDimension = $request->findDimensionQuery($dimensionName);
                if (!isset($selectedDimension) && !isset($queriedDimension)) {
                    continue;
                }

                // checking if at least one returned column is unique
                $selectedUniqueColumn = NULL;
                if (isset($selectedDimension)) {
                    $selectedColumnNames = $selectedDimension->getColumnNames();
                    if (isset($selectedColumnNames)) {
                        // 02/26/2014 it is possible to have columns but not lookup dataset. the case is when we connect with extension table (PK-to-PK connection)
                        if (isset($dimension->datasetName)) {
                            $selectedUniqueColumn = FALSE;
                        }
                        else {
                            // 07/30/2014 it could be just a column expression ($column->branches)
                            foreach ($selectedColumnNames as $selectedColumnName) {
                                // TODO do not try to optimize query generation for 'complex' references
                                $references = ReferencePathHelper::splitReferencePath($selectedColumnName);
                                if (count($references) > 1) {
                                    $selectedUniqueColumn = FALSE;
                                    break;
                                }
                            }
                        }
                    }
                }

                $queriedByColumns = FALSE;
                if (isset($queriedDimension)) {
                    $queriedColumnNames = $queriedDimension->getColumnNames();
                    if (isset($queriedColumnNames)) {
                        if (isset($dimension->datasetName)) {
                            $queriedByColumns = TRUE;
                        }
                    }
                }

                $joinWithLookup = FALSE;
                if (!isset($selectedUniqueColumn) && !$queriedByColumns) {
                    // there is not need to join with lookup. We do not work with any columns
                    $joinWithLookup = NULL;
                }
                elseif ($foundNonAdditiveMeasure) {
                    $joinWithLookup = TRUE;
                }
                elseif ($queriedByColumns) {
                    $joinWithLookup = TRUE;
                }
                elseif ($selectedUniqueColumn === FALSE) {
                    $joinWithLookup = TRUE;
                }

                // FIXME to temporary resolve an issue when joining datasets. We need to change a way SQL engine works
                if (isset($request->referencedRequests) || $request->referenced) {
                    $joinWithLookup = TRUE;
                }

                $generationContext->dimensionJoinPhase[__DefaultQueryEngine_StatementGenerationContext::DIMENSION_JOIN_PHASE__GROUPING_INITIAL][$dimensionName] =
                    isset($joinWithLookup) ? $joinWithLookup : FALSE;
                $generationContext->dimensionJoinPhase[__DefaultQueryEngine_StatementGenerationContext::DIMENSION_JOIN_PHASE__GROUPING_WITH_LOOKUP_AFTER][$dimensionName] =
                    isset($joinWithLookup) ? !$joinWithLookup : FALSE;
            }
        }

        return $generationContext;
    }