mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
Merge pull request #52635 from hendrik-m/table-names-as-string-literal
Allow writing table name as a string literal
This commit is contained in:
commit
e5d3e348ce
@ -34,7 +34,13 @@ The binary you just downloaded can run all sorts of ClickHouse tools and utiliti
|
||||
|
||||
A common use of `clickhouse-local` is to run ad-hoc queries on files: where you don't have to insert the data into a table. `clickhouse-local` can stream the data from a file into a temporary table and execute your SQL.
|
||||
|
||||
If the file is sitting on the same machine as `clickhouse-local`, use the `file` table engine. The following `reviews.tsv` file contains a sampling of Amazon product reviews:
|
||||
If the file is sitting on the same machine as `clickhouse-local`, you can simple specify the file to load. The following `reviews.tsv` file contains a sampling of Amazon product reviews:
|
||||
|
||||
```bash
|
||||
./clickhouse local -q "SELECT * FROM 'reviews.tsv'"
|
||||
```
|
||||
|
||||
This command is a shortcut of:
|
||||
|
||||
```bash
|
||||
./clickhouse local -q "SELECT * FROM file('reviews.tsv')"
|
||||
|
@ -243,6 +243,38 @@ bool ParserIdentifier::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
}
|
||||
|
||||
|
||||
bool ParserTableAsStringLiteralIdentifier::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
if (pos->type != TokenType::StringLiteral)
|
||||
return false;
|
||||
|
||||
ReadBufferFromMemory in(pos->begin, pos->size());
|
||||
String s;
|
||||
|
||||
if (!tryReadQuotedStringInto(s, in))
|
||||
{
|
||||
expected.add(pos, "string literal");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in.count() != pos->size())
|
||||
{
|
||||
expected.add(pos, "string literal");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
expected.add(pos, "non-empty string literal");
|
||||
return false;
|
||||
}
|
||||
|
||||
node = std::make_shared<ASTTableIdentifier>(s);
|
||||
++pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserCompoundIdentifier::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
ASTPtr id_list;
|
||||
|
@ -34,6 +34,19 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
/** An identifier for tables written as string literal, for example, 'mytable.avro'
|
||||
*/
|
||||
class ParserTableAsStringLiteralIdentifier : public IParserBase
|
||||
{
|
||||
public:
|
||||
explicit ParserTableAsStringLiteralIdentifier() {}
|
||||
|
||||
protected:
|
||||
const char * getName() const override { return "string literal table identifier"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||
};
|
||||
|
||||
|
||||
/** An identifier, possibly containing a dot, for example, x_yz123 or `something special` or Hits.EventTime,
|
||||
* possibly with UUID clause like `db name`.`table name` UUID 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
|
||||
*/
|
||||
|
@ -24,6 +24,8 @@ bool ParserTableExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
||||
if (!ParserWithOptionalAlias(std::make_unique<ParserSubquery>(), allow_alias_without_as_keyword).parse(pos, res->subquery, expected)
|
||||
&& !ParserWithOptionalAlias(std::make_unique<ParserFunction>(false, true), allow_alias_without_as_keyword).parse(pos, res->table_function, expected)
|
||||
&& !ParserWithOptionalAlias(std::make_unique<ParserCompoundIdentifier>(true, true), allow_alias_without_as_keyword)
|
||||
.parse(pos, res->database_and_table_name, expected)
|
||||
&& !ParserWithOptionalAlias(std::make_unique<ParserTableAsStringLiteralIdentifier>(), allow_alias_without_as_keyword)
|
||||
.parse(pos, res->database_and_table_name, expected))
|
||||
return false;
|
||||
|
||||
|
@ -0,0 +1,27 @@
|
||||
Test 1: check double quotes
|
||||
1 abc 123 abacaba
|
||||
2 def 456 bacabaa
|
||||
3 story 78912 acabaab
|
||||
4 history 21321321 cabaaba
|
||||
Test 1a: check double quotes no parsing overflow
|
||||
1
|
||||
Test 1b: check double quotes empty
|
||||
1
|
||||
Test 2: check back quotes
|
||||
1 abc 123 abacaba
|
||||
2 def 456 bacabaa
|
||||
3 story 78912 acabaab
|
||||
4 history 21321321 cabaaba
|
||||
Test 2a: check back quotes no parsing overflow
|
||||
1
|
||||
Test 2b: check back quotes empty
|
||||
1
|
||||
Test 3: check literal
|
||||
1 abc 123 abacaba
|
||||
2 def 456 bacabaa
|
||||
3 story 78912 acabaab
|
||||
4 history 21321321 cabaaba
|
||||
Test 3a: check literal no parsing overflow
|
||||
1
|
||||
Test 3b: check literal empty
|
||||
1
|
56
tests/queries/0_stateless/02816_clickhouse_local_table_name_expressions.sh
Executable file
56
tests/queries/0_stateless/02816_clickhouse_local_table_name_expressions.sh
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
# shellcheck source=../shell_config.sh
|
||||
. "$CURDIR"/../shell_config.sh
|
||||
|
||||
dir=${CLICKHOUSE_TEST_UNIQUE_NAME}
|
||||
[[ -d $dir ]] && rm -rd $dir
|
||||
mkdir $dir
|
||||
|
||||
# Create temporary csv file for tests
|
||||
echo '"id","str","int","text"' > $dir/tmp.csv
|
||||
echo '1,"abc",123,"abacaba"' >> $dir/tmp.csv
|
||||
echo '2,"def",456,"bacabaa"' >> $dir/tmp.csv
|
||||
echo '3,"story",78912,"acabaab"' >> $dir/tmp.csv
|
||||
echo '4,"history",21321321,"cabaaba"' >> $dir/tmp.csv
|
||||
|
||||
#################
|
||||
echo "Test 1: check double quotes"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM \"${dir}/tmp.csv\""
|
||||
#################
|
||||
echo "Test 1a: check double quotes no parsing overflow"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM \"${dir}/tmp.csv\"\"bad\"" 2>&1 | grep -c "UNKNOWN_TABLE"
|
||||
#################
|
||||
echo "Test 1b: check double quotes empty"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM \"\"" 2>&1 | grep -c "SYNTAX_ERROR"
|
||||
#################
|
||||
echo "Test 2: check back quotes"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM \`${dir}/tmp.csv\`"
|
||||
#################
|
||||
echo "Test 2a: check back quotes no parsing overflow"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM \`${dir}/tmp.csv\`\`bad\`" 2>&1 | grep -c "UNKNOWN_TABLE"
|
||||
#################
|
||||
echo "Test 2b: check back quotes empty"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM \`\`" 2>&1 | grep -c "SYNTAX_ERROR"
|
||||
#################
|
||||
echo "Test 3: check literal"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM '${dir}/tmp.csv'"
|
||||
#################
|
||||
echo "Test 3a: check literal no parsing overflow"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM '${dir}/tmp.csv''bad'" 2>&1 | grep -c "SYNTAX_ERROR"
|
||||
#################
|
||||
echo "Test 3b: check literal empty"
|
||||
|
||||
$CLICKHOUSE_LOCAL -q "SELECT * FROM ''" 2>&1 | grep -c "SYNTAX_ERROR"
|
||||
|
||||
# Remove temporary dir with files
|
||||
rm -rd $dir
|
Loading…
Reference in New Issue
Block a user