bbotella commented on code in PR #3831:
URL: https://github.com/apache/cassandra/pull/3831#discussion_r1930760576


##########
pylib/cqlshlib/cql3handling.py:
##########
@@ -380,6 +380,11 @@ def dequote_value(cqlword):
                             ( ender="," [propmapkey]=<term> ":" 
[propmapval]=<term> )*
                       ender="}"
                     ;
+<propertyOrOption> ::= <property>
+                     | "ALL"
+                     | "INDEX"

Review Comment:
   Reading the CEP, I think these names should be plural right? `INDEXES` and 
`TRIGGERS`?



##########
test/unit/org/apache/cassandra/cql3/CQLTester.java:
##########
@@ -1969,24 +1981,82 @@ private static boolean isEmptyContainerNull(DataType 
type,
     }
 
     /**
-     * Determine whether the source and target TableMetadata is equal without 
compare the table name and dropped columns.
+     * Determine whether the source and target TableMetadata is equal without 
compare the table name and dropped columns, and
+     * compare the indexes and triggers of the source and target tables, but 
do not compare their names.
      * @param source the source TableMetadata
      * @param target the target TableMetadata
-     * @param compareParams wether compare table params
+     * @param compareParams wether compare table's params
      * @param compareIndexes wether compare table's indexes
-     * @param compareTrigger wether compare table's triggers
+     * @param compareTriggers wether compare table's triggers
      * */
-    protected boolean equalsWithoutTableNameAndDropCns(TableMetadata source, 
TableMetadata target, boolean compareParams, boolean compareIndexes, boolean 
compareTrigger)
+    protected boolean equalsWithoutTableNameAndDropCns(TableMetadata source, 
TableMetadata target, boolean compareParams, boolean compareIndexes, boolean 
compareTriggers)
     {
         return source.partitioner.equals(target.partitioner)
                && source.kind == target.kind
                && source.flags.equals(target.flags)
                && (!compareParams || source.params.equals(target.params))
-               && (!compareIndexes || source.indexes.equals(target.indexes))
-               && (!compareTrigger || source.triggers.equals(target.triggers))
+               && compareIndexesOrTriggerWithoutName(compareIndexes,
+                                                     compareTriggers,
+                                                     source.indexes,
+                                                     target.indexes,
+                                                     source.triggers,
+                                                     target.triggers,
+                                                     target.keyspace,
+                                                     target.name)
                && columnsEqualWitoutKsTb(source, target);
     }
 
+    /**
+     * Compare the source table and target table's indexes and triggers 
without compare their name,
+     * because the names of the target indexes and triggers are randomly 
genrated base on the source
+     * table name and source keyspace name with a rule thant can see
+     * {@link KeyspaceMetadata#findAvailableTriggerName(String)} and {@link 
KeyspaceMetadata#findAvailableIndexName(String)}
+     * for more detail.
+     * @param compareIndexes wether compare indexes or not
+     * @param compareTriggers wether compare triggers or not
+     * @param sourceIdxes source indexes
+     * @param targetIdxes target indexes
+     * @param sourceTriggers source triggers
+     * @param targetTriggers target triggers
+     * @return true if source table's indexes or triggers are same with target 
table's indexes or triggers without compare keyspace and table name
+     * */
+    private boolean compareIndexesOrTriggerWithoutName(boolean compareIndexes, 
boolean compareTriggers, Indexes sourceIdxes, Indexes targetIdxes, Triggers 
sourceTriggers, Triggers targetTriggers, String targetKs, String targetTb)

Review Comment:
   Similar nit. I think splitting this method into indexes and triggers may 
help with the method signature.



##########
src/java/org/apache/cassandra/cql3/statements/schema/CopyTableStatement.java:
##########
@@ -227,13 +237,50 @@ public void validate(ClientState state)
             Guardrails.tables.guard(totalUserTables + 1, targetTableName, 
false, state);
         }
         validateDefaultTimeToLive(attrs.asNewTableParams());
+
+        if (createLikeOptions.contains(ALL) && createLikeOptions.size() > 1)
+        {
+            throw ire("It is not allowed to use ALL option together with " + 
createLikeOptions.stream().filter(option -> option != 
ALL).sorted().collect(Collectors.toList()));
+        }
+    }
+
+    private void cloneIndexesAndTriggersIfNeeded(TableMetadata.Builder 
builder, TableMetadata sourceTableMeta, KeyspaceMetadata targetKeyspaceMeta, 
String targetTableName)
+    {
+        if (createLikeOptions.contains(INDEX) ||
+            createLikeOptions.contains(ALL))
+        {
+            Indexes.Builder idxBuilder = Indexes.builder();
+            for (IndexMetadata indexMetadata : sourceTableMeta.indexes)
+            {
+                // todo use source index name if target keyspace don't have 
same index name but use random name now as cep-43 described
+                String baseName = targetKeyspaceMeta.name + "_" + 
targetTableName + "_" + indexMetadata.name;
+                String idxName = 
targetKeyspaceMeta.findAvailableIndexName(baseName);
+                idxBuilder.add(IndexMetadata.fromSchemaMetadata(idxName, 
indexMetadata.kind, indexMetadata.options));
+            }
+            builder.indexes(idxBuilder.build());

Review Comment:
   Nit: I think extracting this and the triggers section to their own private 
methods may help with readibility.



##########
test/unit/org/apache/cassandra/schema/createlike/CreateLikeTest.java:
##########
@@ -576,28 +581,135 @@ public void testTriggerOperationOnCopiedTable()
     public void testUnSupportedSchema() throws Throwable
     {
         createTable(sourceKs, "CREATE TABLE %s (a int PRIMARY KEY, b int, c 
text)", "tb");
-        String index = createIndex( "CREATE INDEX ON " + sourceKs + ".tb (c)");
+        String index = createIndex("CREATE INDEX ON " + sourceKs + ".tb (c)");
         assertInvalidThrowMessage("Souce Table '" + targetKs + "." + index + 
"' doesn't exist", InvalidRequestException.class,
-                            "CREATE TABLE " + sourceKs + ".newtb LIKE  " + 
targetKs + "." + index + ";");
+                                  "CREATE TABLE " + sourceKs + ".newtb LIKE  " 
+ targetKs + "." + index + ";");
 
         assertInvalidThrowMessage("System keyspace 'system' is not 
user-modifiable", InvalidRequestException.class,
                                   "CREATE TABLE system.local_clone LIKE 
system.local ;");
         assertInvalidThrowMessage("System keyspace 'system_views' is not 
user-modifiable", InvalidRequestException.class,
                                   "CREATE TABLE system_views.newtb LIKE 
system_views.snapshots ;");
     }
 
+    @Test
+    public void testTableCopyWithIndex()
+    {
+        String sourceTb = createTable(sourceKs, "CREATE TABLE %s (a int 
PRIMARY KEY, b int, c text, d int)", "sourcetb");
+        createIndex(sourceKs, "CREATE INDEX ON %s (b)");
+        createIndex(sourceKs, "CREATE INDEX ON %s (c)");
+        String targetTb = createTableLike("CREATE TABLE %s LIKE %s WITH INDEX 
", sourceTb, sourceKs, targetKs);
+        assertTableMetaEqualsWithoutKs(sourceKs, targetKs, sourceTb, targetTb);
+    }
+
+    @Test
+    public void testTableCopyWithTrigger()
+    {
+        String sourceTb = createTable(sourceKs, "CREATE TABLE %s (a int 
PRIMARY KEY, b int, c text, d int)", "sourcetb");
+        createTrigger(sourceKs, "sourcetb", "trigger_1", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass1 + "'");
+        createTrigger(sourceKs, "sourcetb", "trigger_2", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass2 + "'");
+        String targetTb = createTableLike("CREATE TABLE %s LIKE %s WITH 
TRIGGER", sourceTb, sourceKs, targetKs);
+        assertTableMetaEqualsWithoutKs(sourceKs, targetKs, sourceTb, targetTb);
+    }
+
+    @Test
+    public void testTableCopyWithIndexAndTrigger()
+    {
+        String sourceTb = createTable(sourceKs, "CREATE TABLE %s (a int 
PRIMARY KEY, b int, c text, d int)", "sourcetb");
+        createIndex(sourceKs, "CREATE INDEX ON %s (b)");
+        createIndex(sourceKs, "CREATE INDEX ON %s (d)");
+        createTrigger(sourceKs, "sourcetb", "trigger_1", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass1 + "'");
+        createTrigger(sourceKs, "sourcetb", "trigger_2", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass2 + "'");
+        createTrigger(sourceKs, "sourcetb", "trigger_3", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass2 + "'");
+        String targetTb = createTableLike("CREATE TABLE %s LIKE %s WITH 
TRIGGER AND INDEX", sourceTb, sourceKs, targetKs);
+        assertTableMetaEqualsWithoutKs(sourceKs, targetKs, sourceTb, targetTb);
+    }
+
+    @Test
+    public void testTableCopyWithAllOption()
+    {
+        String sourceTb = createTable(sourceKs, "CREATE TABLE %s (a int 
PRIMARY KEY, b int, c text, d int)", "sourcetb");
+        createIndex(sourceKs, "CREATE INDEX ON %s (b)");
+        createTrigger(sourceKs, "sourcetb", "trigger_1", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass1 + "'");
+        createTrigger(sourceKs, "sourcetb", "trigger_2", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass2 + "'");
+        String targetTb = createTableLike("CREATE TABLE %s LIKE %s WITH ALL ", 
sourceTb, sourceKs, targetKs);
+        assertTableMetaEqualsWithoutKs(sourceKs, targetKs, sourceTb, targetTb);
+    }
+
+    @Test
+    public void testTableCopyOptionAndTableProperty()
+    {
+        String sourceTb = createTable(sourceKs, "CREATE TABLE %s (a int 
PRIMARY KEY, b int, c text, d int)", "sourcetb");
+        createIndex(sourceKs, "CREATE INDEX ON %s (b)");
+        createTrigger(sourceKs, "sourcetb", "trigger_1", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass1 + "'");
+        String targetTbWithAll = createTableLike("CREATE TABLE %s LIKE %s WITH 
ALL AND crc_check_chance = 0.8 AND cdc = true", sourceTb, sourceKs, targetKs);
+        assertTableMetaEqualsWithoutKs(sourceKs, targetKs, sourceTb, 
targetTbWithAll, false, false, false);
+
+        TableMetadata source = getTableMetadata(sourceKs, sourceTb);
+        TableMetadata target = getTableMetadata(targetKs, targetTbWithAll);
+        assertNotEquals(source.params, target.params);
+        assertTrue(target.params.cdc);
+        assertFalse(source.params.cdc);
+        assertEquals(0.8, target.params.crcCheckChance, 0.0);
+
+        String targetTbWithTrigger = createTableLike("CREATE TABLE %s LIKE %s 
WITH TRIGGER AND crc_check_chance = 0.8 AND cdc = true", sourceTb, sourceKs, 
targetKs);
+        assertTableMetaEqualsWithoutKs(sourceKs, targetKs, sourceTb, 
targetTbWithTrigger, false, false, false);
+
+        source = getTableMetadata(sourceKs, sourceTb);
+        target = getTableMetadata(targetKs, targetTbWithTrigger);
+        assertNotEquals(source.params, target.params);
+        assertTrue(target.params.cdc);
+        assertFalse(source.params.cdc);
+        assertEquals(0.8, target.params.crcCheckChance, 0.0);
+    }
+
+    @Test
+    public void testUnSupportedCopyofIndexAndTrigger() throws Throwable
+    {
+        createTable(sourceKs, "CREATE TABLE %s (a int PRIMARY KEY, b int, c 
text, d int)", "sourcetb");
+        createIndex(sourceKs, "CREATE INDEX ON %s (b)");
+        createTrigger(sourceKs, "sourcetb", "trigger_1", "CREATE TRIGGER %s ON 
%s USING '" + triggerClass1 + "'");
+        // ALL and TRIGGERS is not allowed
+        assertInvalidThrowMessage("It is not allowed to use ALL option 
together with [TRIGGER]",
+                                  InvalidRequestException.class,
+                                  "CREATE TABLE " + targetKs + ".targettb LIKE 
" + sourceKs + ".sourcetb WITH TRIGGER AND ALL");
+        // ALL and INDEXES is not allowed
+        assertInvalidThrowMessage("It is not allowed to use ALL option 
together with [INDEX]",
+                                  InvalidRequestException.class,
+                                  "CREATE TABLE " + targetKs + ".targettb LIKE 
" + sourceKs + ".sourcetb WITH INDEX AND ALL");
+        // ALL and INDEXES and TRIGGERS is not allowed
+        assertInvalidThrowMessage("It is not allowed to use ALL option 
together with [INDEX, TRIGGER]",
+                                  InvalidRequestException.class,
+                                  "CREATE TABLE " + targetKs + ".targettb LIKE 
" + sourceKs + ".sourcetb WITH INDEX AND TRIGGER AND ALL");
+    }
+

Review Comment:
   What about, for completion, adding tests for tables without indexes and 
triggers that are being copied with `LIKE foo WITH INDEX/TRIGGER/ALL`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


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

Reply via email to