Commit aa92c0a5 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

query plan builder extensions

parent f2572162
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ set(FNORDMETRIC_QUERY_SOURCES
    stage/src/fnordmetric/sql/symboltable.cc
    stage/src/fnordmetric/sql/token.cc
    stage/src/fnordmetric/sql/tokenize.cc
    stage/src/fnordmetric/sql_extensions/chartqueryplanbuilder.cc
    stage/src/fnordmetric/sql_extensions/drawstatement.cc)

set(FNORDMETRIC_CLI_SOURCES
+6 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <fnordmetric/sql/resultlist.h>
#include <fnordmetric/sql/tablerepository.h>
#include <fnordmetric/sql_extensions/axisstatement.h>
#include <fnordmetric/sql_extensions/chartqueryplanbuilder.h>
#include <fnordmetric/sql_extensions/drawstatement.h>
#include <fnordmetric/util/runtimeexception.h>

@@ -124,7 +125,11 @@ ui::Canvas* Query::getChart(size_t index) const {
bool Query::addStatement(
    query::ASTNode* statement,
    query::TableRepository* repo) {
  DefaultQueryPlanBuilder query_plan_builder;
  // FIXPAUL this should be initialized only once
  QueryPlanBuilder query_plan_builder;
  query_plan_builder.extend(
      std::unique_ptr<ChartQueryPlanBuilder>(new ChartQueryPlanBuilder()));

  auto query_plan = query_plan_builder.buildQueryPlan(statement, repo);
  if (query_plan == nullptr) {
    fprintf(stderr, "cant build statement");
+23 −48
Original line number Diff line number Diff line
@@ -7,10 +7,8 @@
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <stdlib.h>
#include <assert.h>
// FIXPAUL!!!
#include "queryplanbuilder.h"
#include "astnode.h"
#include "queryplannode.h"
@@ -20,23 +18,21 @@
#include "limitclause.h"
#include "groupby.h"
#include "symboltable.h"
#include "../sql_extensions/drawstatement.h"
#include "../sql_extensions/axisstatement.h"

namespace fnordmetric {
namespace query {

QueryPlanNode* DefaultQueryPlanBuilder::buildQueryPlan(ASTNode* ast, TableRepository* repo) {
QueryPlanNode* QueryPlanBuilder::buildQueryPlan(
    ASTNode* ast,
    TableRepository* repo) const {
  QueryPlanNode* exec = nullptr;

  /* axis statement */
  if (ast->getType() == ASTNode::T_AXIS) {
    return buildAxisStatement(ast, repo);
  }
  for (const auto& extension : extensions_) {
    exec = extension->buildQueryPlan(ast, repo);

  /* draw statement */
  if (ast->getType() == ASTNode::T_DRAW) {
    return buildDrawStatement(ast);
    if (exec != nullptr) {
      return exec;
    }
  }

  /* internal nodes: multi table query (joins), order, aggregation, limit */
@@ -64,7 +60,7 @@ QueryPlanNode* DefaultQueryPlanBuilder::buildQueryPlan(ASTNode* ast, TableReposi
      "can't figure out a query plan for this, sorry :(");
}

bool DefaultQueryPlanBuilder::hasGroupByClause(ASTNode* ast) {
bool QueryPlanBuilder::hasGroupByClause(ASTNode* ast) const {
  if (!(*ast == ASTNode::T_SELECT) || ast->getChildren().size() < 2) {
    return false;
  }
@@ -78,7 +74,7 @@ bool DefaultQueryPlanBuilder::hasGroupByClause(ASTNode* ast) {
  return false;
}

bool DefaultQueryPlanBuilder::hasAggregationInSelectList(ASTNode* ast) {
bool QueryPlanBuilder::hasAggregationInSelectList(ASTNode* ast) const {
  if (!(*ast == ASTNode::T_SELECT) || ast->getChildren().size() < 2) {
    return false;
  }
@@ -89,7 +85,7 @@ bool DefaultQueryPlanBuilder::hasAggregationInSelectList(ASTNode* ast) {
  return hasAggregationExpression(select_list);
}

bool DefaultQueryPlanBuilder::hasAggregationExpression(ASTNode* ast) {
bool QueryPlanBuilder::hasAggregationExpression(ASTNode* ast) const {
  if (ast->getType() == ASTNode::T_METHOD_CALL) {
    assert(ast->getToken() != nullptr);
    auto symbol = lookupSymbol(ast->getToken()->getString());
@@ -108,36 +104,9 @@ bool DefaultQueryPlanBuilder::hasAggregationExpression(ASTNode* ast) {
  return false;
}

QueryPlanNode* DefaultQueryPlanBuilder::buildDrawStatement(ASTNode* ast) {
  DrawStatement::kDrawStatementType type;
  switch (ast->getToken()->getType()) {
    case Token::T_BAR:
      type = DrawStatement::T_BAR_CHART;
      break;
    case Token::T_LINE:
      type = DrawStatement::T_LINE_CHART;
      break;
    case Token::T_AREA:
      type = DrawStatement::T_AREA_CHART;
      break;
    default:
      RAISE(
          util::RuntimeException,
          "invalid chart type: %s",
          Token::getTypeName(ast->getToken()->getType()));
      return nullptr;
  }

  return new DrawStatement(type);
}

QueryPlanNode* DefaultQueryPlanBuilder::buildAxisStatement(
QueryPlanNode* QueryPlanBuilder::buildGroupBy(
    ASTNode* ast,
    TableRepository* repo) {
  return new AxisStatement();
}

QueryPlanNode* DefaultQueryPlanBuilder::buildGroupBy(ASTNode* ast, TableRepository* repo) {
    TableRepository* repo) const {
  ASTNode group_exprs(ASTNode::T_GROUP_BY);
  assert(ast->getChildren()[0]->getType() == ASTNode::T_SELECT_LIST);

@@ -204,9 +173,9 @@ QueryPlanNode* DefaultQueryPlanBuilder::buildGroupBy(ASTNode* ast, TableReposito
}


bool DefaultQueryPlanBuilder::buildInternalSelectList(
bool QueryPlanBuilder::buildInternalSelectList(
    ASTNode* node,
    ASTNode* target_select_list) {
    ASTNode* target_select_list) const {
  /* search for column references recursively */
  if (node->getType() == ASTNode::T_COLUMN_NAME) {
    auto col_index = -1;
@@ -239,9 +208,9 @@ bool DefaultQueryPlanBuilder::buildInternalSelectList(
  }
}

QueryPlanNode* DefaultQueryPlanBuilder::buildLimitClause(
QueryPlanNode* QueryPlanBuilder::buildLimitClause(
    ASTNode* ast,
    TableRepository* repo) {
    TableRepository* repo) const {
  if (!(*ast == ASTNode::T_SELECT) || ast->getChildren().size() < 3) {
    return nullptr;
  }
@@ -283,5 +252,11 @@ QueryPlanNode* DefaultQueryPlanBuilder::buildLimitClause(
  return nullptr;
}


void QueryPlanBuilder::extend(
    std::unique_ptr<QueryPlanBuilderInterface> other) {
  extensions_.emplace_back(std::move(other));
}

}
}
+23 −19
Original line number Diff line number Diff line
@@ -8,8 +8,8 @@
 * <http://www.gnu.org/licenses/>.
 */

#ifndef _FNORDMETRIC_QUERY_PLANER_H
#define _FNORDMETRIC_QUERY_PLANER_H
#ifndef _FNORDMETRIC_SQL_QUERYPLANBUILDER_H
#define _FNORDMETRIC_SQL_QUERYPLANBUILDER_H
#include <stdlib.h>
#include <string>
#include <vector>
@@ -22,54 +22,57 @@ namespace query {
class QueryPlanNode;
class TableRepository;

class QueryPlanBuilder {
/**
 * All QueryPlanBuilder imeplementations must be thread safe. Specifically they
 * must support calling the buildQueryPlan method concurrenctly from many
 * threads
 */
class QueryPlanBuilderInterface {
public:
  QueryPlanBuilder() {}
  virtual ~QueryPlanBuilder() {}
  QueryPlanBuilderInterface() {}
  virtual ~QueryPlanBuilderInterface() {}

  virtual QueryPlanNode* buildQueryPlan(
      ASTNode* statement,
      TableRepository* repo) = 0;
      TableRepository* repo) const = 0;

};

class DefaultQueryPlanBuilder : public QueryPlanBuilder {
class QueryPlanBuilder : public QueryPlanBuilderInterface {
public:
  DefaultQueryPlanBuilder() {}
  QueryPlanBuilder() {}

  QueryPlanNode* buildQueryPlan(
      ASTNode* statement,
      TableRepository* repo) override;
      TableRepository* repo) const override;

protected:
  void extend(std::unique_ptr<QueryPlanBuilderInterface> other);

  QueryPlanNode* buildDrawStatement(ASTNode* ast);
  QueryPlanNode* buildSeriesStatement(ASTNode* ast, TableRepository* repo);
  QueryPlanNode* buildAxisStatement(ASTNode* ast, TableRepository* repo);
protected:

  /**
   * Returns true if the ast is a SELECT statement that has a GROUP BY clause,
   * otherwise false
   */
  bool hasGroupByClause(ASTNode* ast);
  bool hasGroupByClause(ASTNode* ast) const;

  /**
   * Returns true if the ast is a SELECT statement with a select list that
   * contains at least one aggregation expression, otherwise false.
   */
  bool hasAggregationInSelectList(ASTNode* ast);
  bool hasAggregationInSelectList(ASTNode* ast) const;

  /**
   * Walks the ast recursively and returns true if at least one aggregation
   * expression was found, otherwise false.
   */
  bool hasAggregationExpression(ASTNode* ast);
  bool hasAggregationExpression(ASTNode* ast) const;

  /**
   * Build a group by query plan node for a SELECT statement that has a GROUP
   * BY clause
   */
  QueryPlanNode* buildGroupBy(ASTNode* ast, TableRepository* repo);
  QueryPlanNode* buildGroupBy(ASTNode* ast, TableRepository* repo) const;

  /**
   * Recursively walk the provided ast and search for column references. For
@@ -79,10 +82,11 @@ protected:
   *
   * This is used to create child select lists for nested query plan nodes.
   */
  bool buildInternalSelectList(ASTNode* ast, ASTNode* select_list);
  bool buildInternalSelectList(ASTNode* ast, ASTNode* select_list) const;

  QueryPlanNode* buildLimitClause(ASTNode* ast, TableRepository* repo);
  QueryPlanNode* buildLimitClause(ASTNode* ast, TableRepository* repo) const;

  std::vector<std::unique_ptr<QueryPlanBuilderInterface>> extensions_;
};

}

src/sql/runtime.h

0 → 100644
+38 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#ifndef _FNORDMETRIC_SQL_RUNTIME_H
#define _FNORDMETRIC_SQL_RUNTIME_H
#include <stdlib.h>
#include <string>
#include <vector>
#include <memory>

namespace fnordmetric {
namespace query {

/**
 * A runtime can only be used within a a single thread!
 */
class Runtime {
public:
  Runtime();

  std::unique_ptr<QueryPlan> buildQueryPlan

  void addQueryPlanBuilder(
      std::unique_ptr<QueryPlanBuilder> query_plan_builder);

protected:
  std::vector<std::unique_ptr<QueryPlanBuilder>> query_plan_builders_;
};

}
}
#endif
Loading