Merge pull request #70593 from jsc0218/InsertWith

With Insert Support
This commit is contained in:
Alexey Milovidov 2024-10-21 02:55:44 +00:00 committed by GitHub
commit 4c9e4699df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 114 additions and 1 deletions

View File

@ -121,6 +121,14 @@ However, you can delete old data using `ALTER TABLE ... DROP PARTITION`.
To insert a default value instead of `NULL` into a column with not nullable data type, enable [insert_null_as_default](../../operations/settings/settings.md#insert_null_as_default) setting.
`INSERT` also supports CTE(common table expression). For example, the following two statements are equivalent:
``` sql
INSERT INTO x WITH y AS (SELECT * FROM numbers(10)) SELECT * FROM y;
WITH y AS (SELECT * FROM numbers(10)) INSERT INTO x SELECT * FROM y;
```
## Inserting Data from a File
**Syntax**

View File

@ -1,5 +1,6 @@
#include <Parsers/ASTIdentifier_fwd.h>
#include <Parsers/ASTInsertQuery.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTSelectWithUnionQuery.h>
#include <Parsers/CommonParsers.h>
@ -7,6 +8,7 @@
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/ParserSelectWithUnionQuery.h>
#include <Parsers/ParserWatchQuery.h>
#include <Parsers/ParserWithElement.h>
#include <Parsers/ParserInsertQuery.h>
#include <Parsers/ParserSetQuery.h>
#include <Parsers/InsertQuerySettingsPushDownVisitor.h>
@ -58,10 +60,20 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
ASTPtr settings_ast;
ASTPtr partition_by_expr;
ASTPtr compression;
ASTPtr with_expression_list;
/// Insertion data
const char * data = nullptr;
if (s_with.ignore(pos, expected))
{
if (!ParserList(std::make_unique<ParserWithElement>(), std::make_unique<ParserToken>(TokenType::Comma))
.parse(pos, with_expression_list, expected))
return false;
if (with_expression_list->children.empty())
return false;
}
/// Check for key words `INSERT INTO`. If it isn't found, the query can't be parsed as insert query.
if (!s_insert_into.ignore(pos, expected))
return false;
@ -162,7 +174,7 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
tryGetIdentifierNameInto(format, format_str);
}
else if (s_select.ignore(pos, expected) || s_with.ignore(pos,expected))
else if (s_select.ignore(pos, expected) || s_with.ignore(pos, expected))
{
/// If SELECT is defined, return to position before select and parse
/// rest of query as SELECT query.
@ -170,6 +182,19 @@ bool ParserInsertQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
ParserSelectWithUnionQuery select_p;
select_p.parse(pos, select, expected);
if (with_expression_list)
{
const auto & children = select->as<ASTSelectWithUnionQuery>()->list_of_selects->children;
for (const auto & child : children)
{
if (child->as<ASTSelectQuery>()->getExpression(ASTSelectQuery::Expression::WITH, false))
throw Exception(ErrorCodes::SYNTAX_ERROR,
"Only one WITH should be presented, either before INSERT or SELECT.");
child->as<ASTSelectQuery>()->setExpression(ASTSelectQuery::Expression::WITH,
std::move(with_expression_list));
}
}
/// FORMAT section is expected if we have input() in SELECT part
if (s_format.ignore(pos, expected) && !name_p.parse(pos, format, expected))
return false;

View File

@ -0,0 +1,20 @@
0
1
2
3
4
0
1
2
3
4
2025-01-01
2026-01-01
2027-01-01
2028-01-01
2029-01-01
2030-01-01
2031-01-01
2032-01-01
2033-01-01
2034-01-01

View File

@ -0,0 +1,49 @@
DROP TABLE IF EXISTS x;
CREATE TABLE x ENGINE = Log AS SELECT * FROM numbers(0);
SYSTEM STOP MERGES x;
WITH y AS
(
SELECT *
FROM numbers(10)
)
INSERT INTO x
SELECT *
FROM y
INTERSECT
SELECT *
FROM numbers(5);
WITH y AS
(
SELECT *
FROM numbers(10)
)
INSERT INTO x
SELECT *
FROM numbers(5)
INTERSECT
SELECT *
FROM y;
SELECT * FROM x;
DROP TABLE x;
CREATE TABLE x (d date) ENGINE = Log;
WITH y AS
(
SELECT
number,
date_add(YEAR, number, toDate('2025-01-01')) AS new_date
FROM numbers(10)
)
INSERT INTO x
SELECT y.new_date FROM y;
SELECT * FROM x;
DROP TABLE x;

View File

@ -0,0 +1 @@
Only one WITH should be presented, either before INSERT or SELECT

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
CUR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CUR_DIR"/../shell_config.sh
$CLICKHOUSE_CLIENT -q 'DROP TABLE IF EXISTS x'
$CLICKHOUSE_CLIENT -q 'CREATE TABLE x ENGINE = Log AS SELECT * FROM numbers(0)'
$CLICKHOUSE_CLIENT -q 'WITH y AS ( SELECT * FROM numbers(10) ) INSERT INTO x WITH y2 AS ( SELECT * FROM numbers(10) ) SELECT * FROM y;' |& grep --max-count 1 -F --only-matching "Only one WITH should be presented, either before INSERT or SELECT"
$CLICKHOUSE_CLIENT -q 'DROP TABLE x'