|
48 | 48 | import static java.lang.String.format;
|
49 | 49 | import static java.util.stream.Collectors.toList;
|
50 | 50 | import static java.util.stream.Collectors.toSet;
|
51 |
| -import static org.apache.cassandra.schema.IndexMetadata.isNameValid; |
| 51 | +import static org.apache.cassandra.db.Directories.SECONDARY_INDEX_NAME_SEPARATOR; |
| 52 | +import static org.apache.cassandra.db.Directories.TABLE_DIRECTORY_NAME_SEPARATOR; |
| 53 | +import static org.apache.cassandra.schema.KeyspaceMetadata.validateKeyspaceName; |
| 54 | +import static org.apache.cassandra.schema.SchemaConstants.FILENAME_LENGTH; |
| 55 | +import static org.apache.cassandra.schema.SchemaConstants.TABLE_NAME_LENGTH; |
| 56 | +import static org.apache.cassandra.schema.SchemaConstants.isValidCharsName; |
52 | 57 |
|
53 | 58 | @Unmetered
|
54 | 59 | public class TableMetadata implements SchemaElement
|
@@ -415,11 +420,9 @@ public boolean hasStaticColumns()
|
415 | 420 |
|
416 | 421 | public void validate()
|
417 | 422 | {
|
418 |
| - if (!isNameValid(keyspace)) |
419 |
| - except("Keyspace name must not be empty, more than %s characters long, or contain non-alphanumeric-underscore characters (got \"%s\")", SchemaConstants.NAME_LENGTH, keyspace); |
| 423 | + validateKeyspaceName(keyspace, this::prepareConfigurationException); |
420 | 424 |
|
421 |
| - if (!isNameValid(name)) |
422 |
| - except("Table name must not be empty, more than %s characters long, or contain non-alphanumeric-underscore characters (got \"%s\")", SchemaConstants.NAME_LENGTH, name); |
| 425 | + validateTableName(); |
423 | 426 |
|
424 | 427 | params.validate();
|
425 | 428 |
|
@@ -447,6 +450,17 @@ public void validate()
|
447 | 450 | indexes.validate(this);
|
448 | 451 | }
|
449 | 452 |
|
| 453 | + private void validateTableName() |
| 454 | + { |
| 455 | + if (!isValidCharsName(name)) |
| 456 | + except("Table name must not be empty or not contain non-alphanumeric-underscore characters (got \"%s\")", name); |
| 457 | + |
| 458 | + if (name.length() > TABLE_NAME_LENGTH) |
| 459 | + except("Table name must not be more than %d characters long (got %d characters for \"%s\")", TABLE_NAME_LENGTH, name.length(), name); |
| 460 | + |
| 461 | + assert getTableDirectoryName().length() <= FILENAME_LENGTH : String.format("Generated directory name for a table of %d characters doesn't fit the max filename legnth of %s. This unexpectedly wasn't prevented by check of the table name length, %d, to fit %d characters (got table name \"%s\" and generated directory name \"%s\"", getTableDirectoryName().length(), FILENAME_LENGTH, name.length(), TABLE_NAME_LENGTH, name, getTableDirectoryName()); |
| 462 | + } |
| 463 | + |
450 | 464 | /**
|
451 | 465 | * To support backward compatibility with thrift super columns in the C* 3.0+ storage engine, we encode said super
|
452 | 466 | * columns as a CQL {@code map<blob, blob>}. To ensure the name of this map did not conflict with any other user
|
@@ -543,7 +557,41 @@ public ClusteringComparator partitionKeyAsClusteringComparator()
|
543 | 557 | public String indexTableName(IndexMetadata info)
|
544 | 558 | {
|
545 | 559 | // TODO simplify this when info.index_name is guaranteed to be set
|
546 |
| - return name + Directories.SECONDARY_INDEX_NAME_SEPARATOR + info.name; |
| 560 | + return name + SECONDARY_INDEX_NAME_SEPARATOR + info.name; |
| 561 | + } |
| 562 | + |
| 563 | + /** |
| 564 | + * Returns the table part of the index table name or the entire table name |
| 565 | + * if not an index table. |
| 566 | + * @return table name part |
| 567 | + */ |
| 568 | + public String getTableName() |
| 569 | + { |
| 570 | + int idx = name.indexOf(SECONDARY_INDEX_NAME_SEPARATOR); |
| 571 | + return idx >= 0 ? name.substring(0, idx) : name; |
| 572 | + } |
| 573 | + |
| 574 | + /** |
| 575 | + * Generates a directory name for the table by using table part of |
| 576 | + * the (index) table name and table id. |
| 577 | + * @return directory name |
| 578 | + */ |
| 579 | + public String getTableDirectoryName() |
| 580 | + { |
| 581 | + return getTableName() + TABLE_DIRECTORY_NAME_SEPARATOR + id.toHexString(); |
| 582 | + } |
| 583 | + |
| 584 | + /** |
| 585 | + * Returns the index name from the name of an index table |
| 586 | + * including the dot prefixing the index name, see {@link #indexTableName}. |
| 587 | + * If not an index table, returns null. |
| 588 | + * @return index name prefixed with dot prefix or null |
| 589 | + */ |
| 590 | + @Nullable |
| 591 | + public String getIndexNameWithDot() |
| 592 | + { |
| 593 | + int idx = name.indexOf(SECONDARY_INDEX_NAME_SEPARATOR); |
| 594 | + return idx >= 0 ? name.substring(idx) : null; |
547 | 595 | }
|
548 | 596 |
|
549 | 597 | /**
|
@@ -601,9 +649,14 @@ public TableMetadata withUpdatedUserType(UserType udt)
|
601 | 649 | return builder.build();
|
602 | 650 | }
|
603 | 651 |
|
| 652 | + private ConfigurationException prepareConfigurationException(String format, Object... args) |
| 653 | + { |
| 654 | + return new ConfigurationException(keyspace + '.' + name + ": " + format(format, args)); |
| 655 | + } |
| 656 | + |
604 | 657 | protected void except(String format, Object... args)
|
605 | 658 | {
|
606 |
| - throw new ConfigurationException(keyspace + "." + name + ": " + format(format, args)); |
| 659 | + throw prepareConfigurationException(format, args); |
607 | 660 | }
|
608 | 661 |
|
609 | 662 | @Override
|
|
0 commit comments