sql: initial EXTRACT(... FROM ...) support (#2196)

* start

* wip

* wip

* wip

* wip

* wip

* Fix clickhouse-server.postinst

* clean

* wip

* clean

* clean

* clean

* wip

* clean

* Update dump_variable.cpp
This commit is contained in:
proller 2018-04-13 12:35:08 -07:00 committed by alexey-milovidov
parent d19a56aa3a
commit f9cd6a09e6
7 changed files with 182 additions and 2 deletions

View File

@ -374,6 +374,69 @@ bool ParserCastExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expect
return true; return true;
} }
bool ParserExtractExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
auto begin = pos;
ParserIdentifier id_parser;
ASTPtr identifier;
if (!id_parser.parse(pos, identifier, expected))
return false;
if (pos->type != TokenType::OpeningRoundBracket)
return false;
++pos;
ASTPtr expr;
const char * function_name = nullptr;
if (ParserKeyword("SECOND").ignore(pos, expected))
function_name = "toSecond";
else if (ParserKeyword("MINUTE").ignore(pos, expected))
function_name = "toMinute";
else if (ParserKeyword("HOUR").ignore(pos, expected))
function_name = "toHour";
else if (ParserKeyword("DAY").ignore(pos, expected))
function_name = "toDayOfMonth";
// TODO: SELECT toRelativeWeekNum(toDate('2017-06-15')) - toRelativeWeekNum(toStartOfYear(toDate('2017-06-15')))
// else if (ParserKeyword("WEEK").ignore(pos, expected))
// function_name = "toRelativeWeekNum";
else if (ParserKeyword("MONTH").ignore(pos, expected))
function_name = "toMonth";
else if (ParserKeyword("YEAR").ignore(pos, expected))
function_name = "toYear";
else
return false;
ParserKeyword s_from("FROM");
if (!s_from.ignore(pos, expected))
return false;
ParserExpression elem_parser;
if (!elem_parser.parse(pos, expr, expected))
return false;
if (pos->type != TokenType::ClosingRoundBracket)
return false;
++pos;
auto function = std::make_shared<ASTFunction>();
auto exp_list = std::make_shared<ASTExpressionList>();
function->range.first = begin->begin;
function->range.second = pos->begin;
function->name = function_name; //"toYear";
function->arguments = exp_list;
function->children.push_back(exp_list);
exp_list->children.push_back(expr);
exp_list->range.first = begin->begin;
exp_list->range.second = pos->begin;
node = function;
return true;
}
bool ParserNull::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) bool ParserNull::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{ {
@ -677,7 +740,8 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
ParserArray array_p; ParserArray array_p;
ParserArrayOfLiterals array_lite_p; ParserArrayOfLiterals array_lite_p;
ParserLiteral lit_p; ParserLiteral lit_p;
ParserCastExpression fun_p; ParserExtractExpression extract_p;
ParserCastExpression cast_p;
ParserCompoundIdentifier id_p; ParserCompoundIdentifier id_p;
ParserAsterisk asterisk_p; ParserAsterisk asterisk_p;
ParserQualifiedAsterisk qualified_asterisk_p; ParserQualifiedAsterisk qualified_asterisk_p;
@ -697,7 +761,10 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
if (lit_p.parse(pos, node, expected)) if (lit_p.parse(pos, node, expected))
return true; return true;
if (fun_p.parse(pos, node, expected)) if (extract_p.parse(pos, node, expected))
return true;
if (cast_p.parse(pos, node, expected))
return true; return true;
if (qualified_asterisk_p.parse(pos, node, expected)) if (qualified_asterisk_p.parse(pos, node, expected))

View File

@ -99,6 +99,15 @@ protected:
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
}; };
class ParserExtractExpression : public IParserBase
{
static constexpr auto name = "EXTRACT";
protected:
const char * getName() const override { return name; }
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
};
/** NULL literal. /** NULL literal.
*/ */

View File

@ -0,0 +1,22 @@
#include "iostream_debug_helpers.h"
#include <Parsers/IParser.h>
#include <Parsers/Lexer.h>
#include <Parsers/TokenIterator.h>
namespace DB
{
std::ostream & operator<<(std::ostream & stream, const Token & what) {
stream << "Token (type="<< static_cast<int>(what.type) <<"){"<< std::string{what.begin, what.end} << "}";
return stream;
}
std::ostream & operator<<(std::ostream & stream, const Expected & what) {
stream << "Expected {variants=";
dumpValue(stream, what.variants)
<< "; max_parsed_pos=" << what.max_parsed_pos << "}";
return stream;
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <iostream>
namespace DB
{
class Token;
std::ostream & operator<<(std::ostream & stream, const Token & what);
struct Expected;
std::ostream & operator<<(std::ostream & stream, const Expected & what);
}
#include <Core/iostream_debug_helpers.h>

View File

@ -0,0 +1,10 @@
15
6
2017
58
59
18
31
12
2017
2008 10 11 13 23 44

View File

@ -0,0 +1,39 @@
SELECT EXTRACT(DAY FROM toDate('2017-06-15'));
SELECT EXTRACT (MONTH FROM toDate('2017-06-15'));
SELECT EXTRACT(YEAR FROM toDate('2017-06-15'));
SELECT EXTRACT(SECOND FROM toDateTime('2017-12-31 18:59:58'));
SELECT EXTRACT(MINUTE FROM toDateTime('2017-12-31 18:59:58'));
SELECT EXTRACT(HOUR FROM toDateTime('2017-12-31 18:59:58'));
SELECT EXTRACT(DAY from toDateTime('2017-12-31 18:59:58'));
SELECT extract(MONTH FROM toDateTime('2017-12-31 18:59:58'));
SELECT EXTRACT(year FROM toDateTime('2017-12-31 18:59:58'));
DROP TABLE IF EXISTS test.Orders;
CREATE TABLE test.Orders (OrderId UInt64, OrderName String, OrderDate DateTime) engine = Log;
insert into test.Orders values (1, 'Jarlsberg Cheese', toDateTime('2008-10-11 13:23:44'));
SELECT EXTRACT(YEAR FROM OrderDate) AS OrderYear, EXTRACT(MONTH FROM OrderDate) AS OrderMonth, EXTRACT(DAY FROM OrderDate) AS OrderDay,
EXTRACT(HOUR FROM OrderDate), EXTRACT(MINUTE FROM OrderDate), EXTRACT(SECOND FROM OrderDate) FROM test.Orders WHERE OrderId=1;
DROP TABLE test.Orders;
-- TODO:
-- SELECT EXTRACT(WEEK FROM toDate('2017-06-15'));
-- SELECT EXTRACT(WEEK FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(MINUTE_SECOND FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(HOUR_SECOND FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(HOUR_MINUTE FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(DAY_SECOND FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(DAY_MINUTE FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(DAY_HOUR FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(YEAR_MONTH FROM toDateTime('2017-12-31 18:59:58'));
-- SELECT EXTRACT(QUARTER FROM toDate('2017-06-15'));
-- SELECT EXTRACT(DAY_SECOND FROM toDate('2017-06-15'));
-- SELECT EXTRACT(DAY_MINUTE FROM toDate('2017-06-15'));
-- SELECT EXTRACT(DAY_HOUR FROM toDate('2017-06-15'));
-- SELECT EXTRACT(YEAR_MONTH FROM toDate('2017-06-15'));
-- SELECT EXTRACT(QUARTER FROM toDateTime('2017-12-31 18:59:58'));
-- Maybe:
-- SELECT EXTRACT (YEAR FROM DATE '2014-08-22') AS RESULT;

View File

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <map> #include <map>
#include <set>
#include <tuple> #include <tuple>
#include <array> #include <array>
#include <utility> #include <utility>
@ -12,6 +13,18 @@
struct S1; struct S1;
struct S2 {}; struct S2 {};
struct S3
{
std::set<const char *> m1;
};
std::ostream & operator<<(std::ostream & stream, const S3 & what)
{
stream << "S3 {m1=";
dumpValue(stream, what.m1) << "}";
return stream;
}
int main(int, char **) int main(int, char **)
{ {
int x = 1; int x = 1;
@ -47,5 +60,11 @@ int main(int, char **)
DUMP(S2()); DUMP(S2());
std::set<const char *> variants = {"hello", "world"};
DUMP(variants);
S3 s3 {{"hello", "world"}};
DUMP(s3);
return 0; return 0;
} }