This is an automated email from the ASF dual-hosted git repository.

bereng pushed a commit to branch cassandra-4.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit e98be8e3ec7ba68e17ce4b50a9a71b01ebefca1a
Merge: 14af149 8f4ae7d
Author: Bereng <berenguerbl...@gmail.com>
AuthorDate: Mon Sep 20 09:44:02 2021 +0200

    Merge branch 'cassandra-3.11' into cassandra-4.0

 .../cassandra/cql3/statements/schema/AlterViewStatement.java  |  5 +++--
 test/unit/org/apache/cassandra/cql3/ViewTimesTest.java        | 11 ++++++++++-
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --cc 
src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java
index 1931bb4,0000000..3493eb0
mode 100644,000000..100644
--- 
a/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java
+++ 
b/src/java/org/apache/cassandra/cql3/statements/schema/AlterViewStatement.java
@@@ -1,117 -1,0 +1,118 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.cassandra.cql3.statements.schema;
 +
 +import org.apache.cassandra.audit.AuditLogContext;
 +import org.apache.cassandra.audit.AuditLogEntryType;
 +import org.apache.cassandra.auth.Permission;
 +import org.apache.cassandra.cql3.CQLStatement;
 +import org.apache.cassandra.cql3.QualifiedName;
 +import org.apache.cassandra.schema.*;
 +import org.apache.cassandra.schema.Keyspaces.KeyspacesDiff;
 +import org.apache.cassandra.service.ClientState;
 +import org.apache.cassandra.transport.Event.SchemaChange;
 +import org.apache.cassandra.transport.Event.SchemaChange.Change;
 +import org.apache.cassandra.transport.Event.SchemaChange.Target;
 +
 +public final class AlterViewStatement extends AlterSchemaStatement
 +{
 +    private final String viewName;
 +    private final TableAttributes attrs;
 +
 +    public AlterViewStatement(String keyspaceName, String viewName, 
TableAttributes attrs)
 +    {
 +        super(keyspaceName);
 +        this.viewName = viewName;
 +        this.attrs = attrs;
 +    }
 +
 +    public Keyspaces apply(Keyspaces schema)
 +    {
 +        KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
 +
 +        ViewMetadata view = null == keyspace
 +                          ? null
 +                          : keyspace.views.getNullable(viewName);
 +
 +        if (null == view)
 +            throw ire("Materialized view '%s.%s' doesn't exist", 
keyspaceName, viewName);
 +
 +        attrs.validate();
 +
 +        TableParams params = attrs.asAlteredTableParams(view.metadata.params);
 +
 +        if (params.gcGraceSeconds == 0)
 +        {
 +            throw ire("Cannot alter gc_grace_seconds of a materialized view 
to 0, since this " +
 +                      "value is used to TTL undelivered updates. Setting 
gc_grace_seconds too " +
 +                      "low might cause undelivered updates to expire before 
being replayed.");
 +        }
 +
 +        if (params.defaultTimeToLive > 0)
 +        {
-             throw ire("Cannot set or alter default_time_to_live for a 
materialized view. " +
++            throw ire("Forbidden default_time_to_live detected for a 
materialized view. " +
 +                      "Data in a materialized view always expire at the same 
time than " +
-                       "the corresponding data in the parent table.");
++                      "the corresponding data in the parent table. 
default_time_to_live " +
++                      "must be set to zero, see CASSANDRA-12868 for more 
information");
 +        }
 +
 +        ViewMetadata newView = view.copy(view.metadata.withSwapped(params));
 +        return 
schema.withAddedOrUpdated(keyspace.withSwapped(keyspace.views.withSwapped(newView)));
 +    }
 +
 +    SchemaChange schemaChangeEvent(KeyspacesDiff diff)
 +    {
 +        return new SchemaChange(Change.UPDATED, Target.TABLE, keyspaceName, 
viewName);
 +    }
 +
 +    public void authorize(ClientState client)
 +    {
 +        ViewMetadata view = Schema.instance.getView(keyspaceName, viewName);
 +        if (null != view)
 +            client.ensureTablePermission(keyspaceName, view.baseTableName, 
Permission.ALTER);
 +    }
 +
 +    @Override
 +    public AuditLogContext getAuditLogContext()
 +    {
 +        return new AuditLogContext(AuditLogEntryType.ALTER_VIEW, 
keyspaceName, viewName);
 +    }
 +
 +    public String toString()
 +    {
 +        return String.format("%s (%s, %s)", getClass().getSimpleName(), 
keyspaceName, viewName);
 +    }
 +
 +    public static final class Raw extends CQLStatement.Raw
 +    {
 +        private final QualifiedName name;
 +        private final TableAttributes attrs;
 +
 +        public Raw(QualifiedName name, TableAttributes attrs)
 +        {
 +            this.name = name;
 +            this.attrs = attrs;
 +        }
 +
 +        public AlterViewStatement prepare(ClientState state)
 +        {
 +            String keyspaceName = name.hasKeyspace() ? name.getKeyspace() : 
state.getKeyspace();
 +            return new AlterViewStatement(keyspaceName, name.getName(), 
attrs);
 +        }
 +    }
 +}
diff --cc test/unit/org/apache/cassandra/cql3/ViewTimesTest.java
index 4fee422,0000000..14d7566
mode 100644,000000..100644
--- a/test/unit/org/apache/cassandra/cql3/ViewTimesTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ViewTimesTest.java
@@@ -1,300 -1,0 +1,309 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package org.apache.cassandra.cql3;
 +
 +import java.util.List;
 +import java.util.concurrent.TimeUnit;
 +
 +import org.junit.Assert;
 +import org.junit.Test;
 +
 +import com.datastax.driver.core.ResultSet;
 +import com.datastax.driver.core.Row;
 +import org.apache.cassandra.db.Keyspace;
 +import org.apache.cassandra.utils.FBUtilities;
 +
++import static org.junit.Assert.assertEquals;
++
 +/*
 + * This test class was too large and used to timeout CASSANDRA-16777. We're 
splitting it into:
 + * - ViewTest
 + * - ViewPKTest
 + * - ViewRangesTest
 + * - ViewTimesTest
 + */
 +public class ViewTimesTest extends ViewAbstractTest
 +{
 +    @Test
 +    public void testRegularColumnTimestampUpdates() throws Throwable
 +    {
 +        // Regression test for CASSANDRA-10910
 +
 +        createTable("CREATE TABLE %s (" +
 +                    "k int PRIMARY KEY, " +
 +                    "c int, " +
 +                    "val int)");
 +
 +        execute("USE " + keyspace());
 +        executeNet("USE " + keyspace());
 +
 +        createView("mv_rctstest", "CREATE MATERIALIZED VIEW %s AS SELECT * 
FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c)");
 +
 +        updateView("UPDATE %s SET c = ?, val = ? WHERE k = ?", 0, 0, 0);
 +        updateView("UPDATE %s SET val = ? WHERE k = ?", 1, 0);
 +        updateView("UPDATE %s SET c = ? WHERE k = ?", 1, 0);
 +        assertRows(execute("SELECT c, k, val FROM mv_rctstest"), row(1, 0, 
1));
 +
 +        updateView("TRUNCATE %s");
 +
 +        updateView("UPDATE %s USING TIMESTAMP 1 SET c = ?, val = ? WHERE k = 
?", 0, 0, 0);
 +        updateView("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE k = ?", 1, 0);
 +        updateView("UPDATE %s USING TIMESTAMP 2 SET val = ? WHERE k = ?", 1, 
0);
 +        updateView("UPDATE %s USING TIMESTAMP 4 SET c = ? WHERE k = ?", 2, 0);
 +        updateView("UPDATE %s USING TIMESTAMP 3 SET val = ? WHERE k = ?", 2, 
0);
 +
 +        assertRows(execute("SELECT c, k, val FROM mv_rctstest"), row(2, 0, 
2));
 +        assertRows(execute("SELECT c, k, val FROM mv_rctstest limit 1"), 
row(2, 0, 2));
 +    }
 +
 +    @Test
 +    public void complexTimestampUpdateTestWithFlush() throws Throwable
 +    {
 +        complexTimestampUpdateTest(true);
 +    }
 +
 +    @Test
 +    public void complexTimestampUpdateTestWithoutFlush() throws Throwable
 +    {
 +        complexTimestampUpdateTest(false);
 +    }
 +
 +    public void complexTimestampUpdateTest(boolean flush) throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, 
PRIMARY KEY (a, b))");
 +
 +        execute("USE " + keyspace());
 +        executeNet("USE " + keyspace());
 +        Keyspace ks = Keyspace.open(keyspace());
 +
 +        createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s 
WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (c, a, b)");
 +        ks.getColumnFamilyStore("mv").disableAutoCompaction();
 +
 +        //Set initial values TS=0, leaving e null and verify view
 +        executeNet("INSERT INTO %s (a, b, c, d) VALUES (0, 0, 1, 0) USING 
TIMESTAMP 0");
 +        assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row(0));
 +
 +        //update c's timestamp TS=2
 +        executeNet("UPDATE %s USING TIMESTAMP 2 SET c = ? WHERE a = ? and b = 
? ", 1, 0, 0);
 +        assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row(0));
 +
 +        if (flush)
 +            FBUtilities.waitOnFutures(ks.flush());
 +
 +        // change c's value and TS=3, tombstones c=1 and adds c=0 record
 +        executeNet("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE a = ? and b = 
? ", 0, 0, 0);
 +        if (flush)
 +            FBUtilities.waitOnFutures(ks.flush());
 +        assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0));
 +
 +        if(flush)
 +        {
 +            ks.getColumnFamilyStore("mv").forceMajorCompaction();
 +            FBUtilities.waitOnFutures(ks.flush());
 +        }
 +
 +
 +        //change c's value back to 1 with TS=4, check we can see d
 +        executeNet("UPDATE %s USING TIMESTAMP 4 SET c = ? WHERE a = ? and b = 
? ", 1, 0, 0);
 +        if (flush)
 +        {
 +            ks.getColumnFamilyStore("mv").forceMajorCompaction();
 +            FBUtilities.waitOnFutures(ks.flush());
 +        }
 +
 +        assertRows(execute("SELECT d,e from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row(0, null));
 +
 +
 +        //Add e value @ TS=1
 +        executeNet("UPDATE %s USING TIMESTAMP 1 SET e = ? WHERE a = ? and b = 
? ", 1, 0, 0);
 +        assertRows(execute("SELECT d,e from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row(0, 1));
 +
 +        if (flush)
 +            FBUtilities.waitOnFutures(ks.flush());
 +
 +
 +        //Change d value @ TS=2
 +        executeNet("UPDATE %s USING TIMESTAMP 2 SET d = ? WHERE a = ? and b = 
? ", 2, 0, 0);
 +        assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row(2));
 +
 +        if (flush)
 +            FBUtilities.waitOnFutures(ks.flush());
 +
 +
 +        //Change d value @ TS=3
 +        executeNet("UPDATE %s USING TIMESTAMP 3 SET d = ? WHERE a = ? and b = 
? ", 1, 0, 0);
 +        assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row(1));
 +
 +
 +        //Tombstone c
 +        executeNet("DELETE FROM %s WHERE a = ? and b = ?", 0, 0);
 +        assertRows(execute("SELECT d from mv"));
 +
 +        //Add back without D
 +        executeNet("INSERT INTO %s (a, b, c) VALUES (0, 0, 1)");
 +
 +        //Make sure D doesn't pop back in.
 +        assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = 
?", 1, 0, 0), row((Object) null));
 +
 +
 +        //New partition
 +        // insert a row with timestamp 0
 +        executeNet("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?) 
USING TIMESTAMP 0", 1, 0, 0, 0, 0);
 +
 +        // overwrite pk and e with timestamp 1, but don't overwrite d
 +        executeNet("INSERT INTO %s (a, b, c, e) VALUES (?, ?, ?, ?) USING 
TIMESTAMP 1", 1, 0, 0, 0);
 +
 +        // delete with timestamp 0 (which should only delete d)
 +        executeNet("DELETE FROM %s USING TIMESTAMP 0 WHERE a = ? AND b = ?", 
1, 0);
 +        assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = 
? and b = ?", 0, 1, 0),
 +                   row(1, 0, 0, null, 0)
 +        );
 +
 +        executeNet("UPDATE %s USING TIMESTAMP 2 SET c = ? WHERE a = ? AND b = 
?", 1, 1, 0);
 +        executeNet("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE a = ? AND b = 
?", 0, 1, 0);
 +        assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = 
? and b = ?", 0, 1, 0),
 +                   row(1, 0, 0, null, 0)
 +        );
 +
 +        executeNet("UPDATE %s USING TIMESTAMP 3 SET d = ? WHERE a = ? AND b = 
?", 0, 1, 0);
 +        assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = 
? and b = ?", 0, 1, 0),
 +                   row(1, 0, 0, 0, 0)
 +        );
 +    }
 +
 +    @Test
 +    public void ttlTest() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (" +
 +                    "a int," +
 +                    "b int," +
 +                    "c int," +
 +                    "d int," +
 +                    "PRIMARY KEY (a, b))");
 +
 +        executeNet("USE " + keyspace());
 +
 +        createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s 
WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)");
 +
 +        updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TTL 
3", 1, 1, 1, 1);
 +
 +        Thread.sleep(TimeUnit.SECONDS.toMillis(1));
 +        updateView("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 1, 1, 2);
 +
 +        Thread.sleep(TimeUnit.SECONDS.toMillis(5));
 +        List<Row> results = executeNet("SELECT d FROM mv WHERE c = 2 AND a = 
1 AND b = 1").all();
 +        Assert.assertEquals(1, results.size());
 +        Assert.assertTrue("There should be a null result given back due to 
ttl expiry", results.get(0).isNull(0));
 +    }
 +
 +    @Test
 +    public void ttlExpirationTest() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (" +
 +                    "a int," +
 +                    "b int," +
 +                    "c int," +
 +                    "d int," +
 +                    "PRIMARY KEY (a, b))");
 +
 +        executeNet("USE " + keyspace());
 +
 +        createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s 
WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)");
 +
 +        updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TTL 
3", 1, 1, 1, 1);
 +
 +        Thread.sleep(TimeUnit.SECONDS.toMillis(4));
 +        Assert.assertEquals(0, executeNet("SELECT * FROM mv WHERE c = 1 AND a 
= 1 AND b = 1").all().size());
 +    }
 +
 +    @Test
 +    public void conflictingTimestampTest() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (" +
 +                    "a int," +
 +                    "b int," +
 +                    "c int," +
 +                    "PRIMARY KEY (a, b))");
 +
 +        executeNet("USE " + keyspace());
 +
 +        createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s 
WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)");
 +
 +        for (int i = 0; i < 50; i++)
 +        {
 +            updateView("INSERT INTO %s (a, b, c) VALUES (?, ?, ?) USING 
TIMESTAMP 1", 1, 1, i);
 +        }
 +
 +        ResultSet mvRows = executeNet("SELECT c FROM mv");
 +        List<Row> rows = executeNet("SELECT c FROM %s").all();
 +        Assert.assertEquals("There should be exactly one row in base", 1, 
rows.size());
 +        int expected = rows.get(0).getInt("c");
 +        assertRowsNet(mvRows, row(expected));
 +    }
 +
 +    @Test
 +    public void testCreateMvWithTTL() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (" +
 +                    "k int PRIMARY KEY, " +
 +                    "c int, " +
 +                    "val int) WITH default_time_to_live = 60");
 +
 +        execute("USE " + keyspace());
 +        executeNet("USE " + keyspace());
 +
 +        // Must NOT include "default_time_to_live" for Materialized View 
creation
 +        try
 +        {
 +            createView("mv_ttl1", "CREATE MATERIALIZED VIEW %s AS SELECT * 
FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c) WITH 
default_time_to_live = 30");
 +            Assert.fail("Should fail if TTL is provided for materialized 
view");
 +        }
 +        catch (Exception e)
 +        {
 +        }
 +    }
 +
 +    @Test
 +    public void testAlterMvWithTTL() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (" +
 +                    "k int PRIMARY KEY, " +
 +                    "c int, " +
 +                    "val int) WITH default_time_to_live = 60");
 +
++        execute("USE " + keyspace());
++        executeNet("USE " + keyspace());
++
 +        createView("mv_ttl2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM 
%%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c)");
 +
 +        // Must NOT include "default_time_to_live" on alter Materialized View
 +        try
 +        {
-             executeNet("ALTER MATERIALIZED VIEW %s WITH default_time_to_live 
= 30");
++            executeNet("ALTER MATERIALIZED VIEW " + keyspace()+ ".mv_ttl2 
WITH default_time_to_live = 30");
 +            Assert.fail("Should fail if TTL is provided while altering 
materialized view");
 +        }
 +        catch (Exception e)
 +        {
++            // Make sure the message is clear. See CASSANDRA-16960
++            assertEquals("Forbidden default_time_to_live detected for a 
materialized view. Data in a materialized view always expire at the same time 
than the corresponding "
++                         + "data in the parent table. default_time_to_live 
must be set to zero, see CASSANDRA-12868 for more information",
++                         e.getMessage());
 +        }
 +    }
 +}

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to