mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-28 02:21:59 +00:00
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:
parent
d19a56aa3a
commit
f9cd6a09e6
@ -374,6 +374,69 @@ bool ParserCastExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expect
|
||||
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)
|
||||
{
|
||||
@ -677,7 +740,8 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp
|
||||
ParserArray array_p;
|
||||
ParserArrayOfLiterals array_lite_p;
|
||||
ParserLiteral lit_p;
|
||||
ParserCastExpression fun_p;
|
||||
ParserExtractExpression extract_p;
|
||||
ParserCastExpression cast_p;
|
||||
ParserCompoundIdentifier id_p;
|
||||
ParserAsterisk 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))
|
||||
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;
|
||||
|
||||
if (qualified_asterisk_p.parse(pos, node, expected))
|
||||
|
@ -99,6 +99,15 @@ protected:
|
||||
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.
|
||||
*/
|
||||
|
22
dbms/src/Parsers/iostream_debug_helpers.cpp
Normal file
22
dbms/src/Parsers/iostream_debug_helpers.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
14
dbms/src/Parsers/iostream_debug_helpers.h
Normal file
14
dbms/src/Parsers/iostream_debug_helpers.h
Normal 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>
|
10
dbms/tests/queries/0_stateless/00619_extract.reference
Normal file
10
dbms/tests/queries/0_stateless/00619_extract.reference
Normal file
@ -0,0 +1,10 @@
|
||||
15
|
||||
6
|
||||
2017
|
||||
58
|
||||
59
|
||||
18
|
||||
31
|
||||
12
|
||||
2017
|
||||
2008 10 11 13 23 44
|
39
dbms/tests/queries/0_stateless/00619_extract.sql
Normal file
39
dbms/tests/queries/0_stateless/00619_extract.sql
Normal 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;
|
@ -4,6 +4,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
@ -12,6 +13,18 @@
|
||||
struct S1;
|
||||
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 x = 1;
|
||||
@ -47,5 +60,11 @@ int main(int, char **)
|
||||
|
||||
DUMP(S2());
|
||||
|
||||
std::set<const char *> variants = {"hello", "world"};
|
||||
DUMP(variants);
|
||||
|
||||
S3 s3 {{"hello", "world"}};
|
||||
DUMP(s3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user