18
18
19
19
package org .apache .cassandra .cql3 .statements .schema ;
20
20
21
+ import java .nio .ByteBuffer ;
22
+ import java .util .Optional ;
23
+ import java .util .Set ;
24
+ import java .util .stream .Collectors ;
25
+
26
+ import com .google .common .collect .Sets ;
27
+
21
28
import org .apache .cassandra .audit .AuditLogContext ;
22
29
import org .apache .cassandra .audit .AuditLogEntryType ;
23
30
import org .apache .cassandra .auth .Permission ;
24
31
import org .apache .cassandra .cql3 .CQLStatement ;
25
32
import org .apache .cassandra .cql3 .QualifiedName ;
26
33
import org .apache .cassandra .db .guardrails .Guardrails ;
34
+ import org .apache .cassandra .db .marshal .UTF8Type ;
35
+ import org .apache .cassandra .db .marshal .UserType ;
27
36
import org .apache .cassandra .db .marshal .VectorType ;
28
37
import org .apache .cassandra .exceptions .AlreadyExistsException ;
29
38
import org .apache .cassandra .schema .Indexes ;
@@ -114,14 +123,39 @@ public Keyspaces apply(ClusterMetadata metadata)
114
123
115
124
if (targetKeyspaceMeta .hasTable (targetTableName ))
116
125
{
117
- if (ifNotExists )
126
+ if (ifNotExists )
118
127
return schema ;
119
128
120
129
throw new AlreadyExistsException (targetKeyspace , targetTableName );
121
130
}
122
- // todo support udt for differenet ks latter
123
- if (!sourceKeyspace .equalsIgnoreCase (targetKeyspace ) && !sourceTableMeta .getReferencedUserTypes ().isEmpty ())
124
- throw ire ("Cannot use CREATE TABLE LIKE across different keyspace when source table have UDTs." );
131
+
132
+ if (!sourceKeyspace .equalsIgnoreCase (targetKeyspace ))
133
+ {
134
+ Set <String > missingUserTypes = Sets .newHashSet ();
135
+ // for different keyspace, if source table used some udts and the target table also need them
136
+ for (ByteBuffer sourceUserTypeName : sourceTableMeta .getReferencedUserTypes ())
137
+ {
138
+ Optional <UserType > targetUserType = targetKeyspaceMeta .types .get (sourceUserTypeName );
139
+ Optional <UserType > sourceUserType = sourceKeyspaceMeta .types .get (sourceUserTypeName );
140
+ if (targetUserType .isPresent () && sourceUserType .isPresent ())
141
+ {
142
+ if (!sourceUserType .get ().equalsWithOutKs (targetUserType .get ()))
143
+ throw ire ("Target keyspace '%s' has same UDT name '%s' as source keyspace '%s' but with different structure." ,
144
+ targetKeyspace ,
145
+ UTF8Type .instance .getString (targetUserType .get ().name ),
146
+ sourceKeyspace );
147
+ }
148
+ else
149
+ {
150
+ missingUserTypes .add (UTF8Type .instance .compose (sourceUserTypeName ));
151
+ }
152
+ }
153
+
154
+ if (!missingUserTypes .isEmpty ())
155
+ throw ire ("UDTs %s do not exist in target keyspace '%s'." ,
156
+ missingUserTypes .stream ().sorted ().collect (Collectors .joining (", " )),
157
+ targetKeyspace );
158
+ }
125
159
126
160
// Guardrail on columns per table
127
161
Guardrails .columnsPerTable .guard (sourceTableMeta .columns ().size (), targetTableName , false , state );
@@ -130,7 +164,7 @@ public Keyspaces apply(ClusterMetadata metadata)
130
164
if (columnMetadata .type .isVector ())
131
165
{
132
166
Guardrails .vectorTypeEnabled .ensureEnabled (columnMetadata .name .toString (), state );
133
- int dimensions = ((VectorType )columnMetadata .type ).dimension ;
167
+ int dimensions = ((VectorType ) columnMetadata .type ).dimension ;
134
168
Guardrails .vectorDimensions .guard (dimensions , columnMetadata .name .toString (), false , state );
135
169
}
136
170
});
0 commit comments