Skip to content

Commit e19c933

Browse files
committed
wip
1 parent ccf12ef commit e19c933

File tree

5 files changed

+112
-5
lines changed

5 files changed

+112
-5
lines changed

src/antlr/Parser.g

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,7 @@ dropMaterializedViewStatement returns [DropViewStatement.Raw stmt]
13121312
*/
13131313
truncateStatement returns [TruncateStatement stmt]
13141314
: K_TRUNCATE (K_COLUMNFAMILY)? cf=columnFamilyName { $stmt = new TruncateStatement(cf); }
1315+
| K_TRUNCATE K_KEYSPACE ks=keyspaceName { $stmt = new TruncateStatement(new SemiQualifiedName(ks)); }
13151316
;
13161317

13171318
/**
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.cassandra.cql3;
20+
21+
public class SemiQualifiedName extends QualifiedName
22+
{
23+
private SemiQualifiedName() {}
24+
25+
public SemiQualifiedName(String keyspace)
26+
{
27+
super(keyspace, null);
28+
}
29+
30+
@Override
31+
public String toString()
32+
{
33+
return getKeyspace();
34+
}
35+
36+
/**
37+
* Returns a string representation of the qualified name that is safe to use directly in CQL queries.
38+
* If necessary, the string will be double-quoted, and any quotes inside the string will be escaped.
39+
*/
40+
public String toCQLString()
41+
{
42+
return String.format("%s", ColumnIdentifier.maybeQuote(getKeyspace()));
43+
}
44+
}

src/java/org/apache/cassandra/cql3/statements/TruncateStatement.java

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
*/
1818
package org.apache.cassandra.cql3.statements;
1919

20+
import java.util.ArrayList;
21+
import java.util.List;
2022
import java.util.concurrent.TimeoutException;
2123

24+
import com.google.common.collect.Iterables;
25+
2226
import org.apache.cassandra.audit.AuditLogContext;
2327
import org.apache.cassandra.audit.AuditLogEntryType;
2428
import org.apache.cassandra.auth.Permission;
@@ -27,6 +31,7 @@
2731
import org.apache.cassandra.db.Keyspace;
2832
import org.apache.cassandra.db.guardrails.Guardrails;
2933
import org.apache.cassandra.db.virtual.VirtualKeyspaceRegistry;
34+
import org.apache.cassandra.db.virtual.VirtualTable;
3035
import org.apache.cassandra.exceptions.*;
3136
import org.apache.cassandra.schema.Schema;
3237
import org.apache.cassandra.schema.TableId;
@@ -39,6 +44,8 @@
3944
import org.apache.commons.lang3.builder.ToStringBuilder;
4045
import org.apache.commons.lang3.builder.ToStringStyle;
4146

47+
import static java.util.stream.Collectors.joining;
48+
4249
public class TruncateStatement extends QualifiedStatement implements CQLStatement
4350
{
4451
public TruncateStatement(QualifiedName name)
@@ -58,16 +65,54 @@ public void authorize(ClientState state) throws InvalidRequestException, Unautho
5865

5966
public void validate(ClientState state) throws InvalidRequestException
6067
{
61-
Schema.instance.validateTable(keyspace(), name());
68+
if (qualifiedName instanceof SemiQualifiedName)
69+
Schema.instance.validateKeyspace(keyspace());
70+
else
71+
Schema.instance.validateTable(keyspace(), name());
72+
6273
Guardrails.dropTruncateTableEnabled.ensureEnabled(state);
6374
}
6475

6576
@Override
6677
public ResultMessage execute(QueryState state, QueryOptions options, Dispatcher.RequestTime requestTime) throws InvalidRequestException, TruncateException
78+
{
79+
if (name() == null)
80+
{
81+
Iterable<TableMetadata> tablesIterable = Iterables.filter(Schema.instance.getTablesAndViews(keyspace()), tmd -> !tmd.isView());
82+
List<TableMetadata> tablesToTruncate = new ArrayList<>();
83+
for (TableMetadata t : tablesIterable)
84+
tablesToTruncate.add(t);
85+
86+
for (TableMetadata tmd : tablesIterable)
87+
{
88+
try
89+
{
90+
truncateOne(tmd.keyspace, tmd.name);
91+
tablesToTruncate.remove(tmd);
92+
}
93+
catch (TruncateException ex)
94+
{
95+
throw new TruncateException(ex, "Tables not truncated: " + tablesToTruncate.stream()
96+
.map(TableMetadata::toString)
97+
.collect(joining(",")));
98+
}
99+
}
100+
}
101+
else
102+
truncateOne(keyspace(), name());
103+
104+
return null;
105+
}
106+
107+
private void truncateOne(String keyspace, String table)
67108
{
68109
try
69110
{
70-
TableMetadata metaData = Schema.instance.getTableMetadata(keyspace(), name());
111+
TableMetadata metaData = Schema.instance.getTableMetadata(keyspace, table);
112+
113+
if (metaData == null)
114+
throw new InvalidRequestException(String.format("Cannot TRUNCATE %s.%s as it does not exist.", keyspace(), name()));
115+
71116
if (metaData.isView())
72117
throw new InvalidRequestException("Cannot TRUNCATE materialized view directly; must truncate base table instead");
73118

@@ -77,21 +122,24 @@ public ResultMessage execute(QueryState state, QueryOptions options, Dispatcher.
77122
}
78123
else
79124
{
80-
StorageProxy.truncateBlocking(keyspace(), name());
125+
StorageProxy.truncateBlocking(keyspace, table);
81126
}
82127
}
83128
catch (UnavailableException | TimeoutException e)
84129
{
85130
throw new TruncateException(e);
86131
}
87-
return null;
88132
}
89133

90134
public ResultMessage executeLocally(QueryState state, QueryOptions options)
91135
{
92136
try
93137
{
94138
TableMetadata metaData = Schema.instance.getTableMetadata(keyspace(), name());
139+
140+
if (metaData == null)
141+
throw new InvalidRequestException(String.format("Cannot TRUNCATE %s.%s as it does not exist.", keyspace(), name()));
142+
95143
if (metaData.isView())
96144
throw new InvalidRequestException("Cannot TRUNCATE materialized view directly; must truncate base table instead");
97145

@@ -114,7 +162,9 @@ public ResultMessage executeLocally(QueryState state, QueryOptions options)
114162

115163
private void executeForVirtualTable(TableId id)
116164
{
117-
VirtualKeyspaceRegistry.instance.getTableNullable(id).truncate();
165+
VirtualTable maybeVTable = VirtualKeyspaceRegistry.instance.getTableNullable(id);
166+
if (maybeVTable != null)
167+
maybeVTable.truncate();
118168
}
119169

120170
@Override

src/java/org/apache/cassandra/exceptions/TruncateException.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919

2020
public class TruncateException extends RequestExecutionException
2121
{
22+
public TruncateException(Throwable e, String msg)
23+
{
24+
super(ExceptionCode.TRUNCATE_ERROR, msg, e);
25+
}
26+
2227
public TruncateException(Throwable e)
2328
{
2429
super(ExceptionCode.TRUNCATE_ERROR, "Error during truncate: " + e.getMessage(), e);

src/java/org/apache/cassandra/schema/SchemaProvider.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ default TableMetadata validateTable(String keyspaceName, String tableName)
104104
return metadata;
105105
}
106106

107+
default KeyspaceMetadata validateKeyspace(String keyspaceName)
108+
{
109+
return Optional.ofNullable(getKeyspaceInstance(keyspaceName))
110+
.map(Keyspace::getMetadata)
111+
.orElseThrow(() -> new InvalidRequestException(String.format("Keyspace %s does not exist", keyspaceName)));
112+
}
113+
107114
default ColumnFamilyStore getColumnFamilyStoreInstance(TableId id)
108115
{
109116
TableMetadata metadata = getTableMetadata(id);

0 commit comments

Comments
 (0)