Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions hoptimator-cli/src/main/java/sqlline/HoptimatorAppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.jline.reader.Completer;

import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -138,7 +137,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
new HoptimatorDriver.Prepare(conn), plan, create, querySql);
}
sqlline.output(plan.sql(conn).apply(SqlDialect.ANSI));
} catch (SQLException e) {
} catch (Exception e) {
sqlline.error(e);
dispatchCallback.setToFailure();
}
Expand Down Expand Up @@ -216,7 +215,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
sqlline.output(resolved.sourceConnectorConfigs().toString() + "\n");
sqlline.output("Sink configs:");
sqlline.output(resolved.sinkConnectorConfigs().toString() + "\n");
} catch (SQLException e) {
} catch (Exception e) {
sqlline.error(e);
dispatchCallback.setToFailure();
}
Expand Down Expand Up @@ -284,7 +283,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
try {
List<String> specs = HoptimatorDdlUtils.specifyFromSql(sql, conn).specs;
specs.forEach(x -> sqlline.output(x + "\n\n---\n\n"));
} catch (SQLException e) {
} catch (Exception e) {
sqlline.error(e);
dispatchCallback.setToFailure();
}
Expand Down Expand Up @@ -414,7 +413,7 @@ public void execute(String line, DispatchCallback dispatchCallback) {
&& depth >= 1 && graph.root() instanceof GraphNode.External && isDegenerate(graph)) {
sqlline.output(degenerateGraphWarning());
}
} catch (SQLException e) {
} catch (Exception e) {
sqlline.error(e);
dispatchCallback.setToFailure();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,27 @@ public static Set<String> parseAnnotation(String annotation) {
return out;
}

/**
* Trims {@code value} to a valid K8s label value: at most {@link #MAX_LABEL_VALUE} characters,
* with leading/trailing non-alphanumeric characters stripped. Truncating at a fixed offset can
* land on a '-', '_', or '.' (e.g. a long table name cut mid-word), which K8s rejects because a
* label value must start and end with an alphanumeric character.
*/
private static String truncate(String value) {
return value.length() <= MAX_LABEL_VALUE ? value : value.substring(0, MAX_LABEL_VALUE);
String truncated = value.length() <= MAX_LABEL_VALUE ? value : value.substring(0, MAX_LABEL_VALUE);
int start = 0;
int end = truncated.length();
while (start < end && !isAlphanumeric(truncated.charAt(start))) {
start++;
}
while (end > start && !isAlphanumeric(truncated.charAt(end - 1))) {
end--;
}
return truncated.substring(start, end);
}

private static boolean isAlphanumeric(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
}

private static byte[] sha256(byte[] input) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ void stampLabelValueTruncatedAtSixtyThreeChars() {
assertTrue(value.length() <= 63);
}

@Test
void stampLabelValueStrippedWhenTruncationLandsOnSeparator() {
// Regression: a real identifier truncated at exactly 63 chars ended on '_', which K8s
// rejects. This dummy path is sized so truncation lands on a '_' too; it must be stripped.
V1ObjectMeta meta = stamp(
Collections.singletonList(
src("__dummy-database", "SCHEMA", "dummy_table_name_for_internal_testing____")),
null);
String value = meta.getLabels().values().iterator().next();

assertTrue(value.length() <= 63);
assertTrue(value.matches("(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?"),
"value must satisfy K8s label-value regex, got: " + value);
assertEquals("dummy-database_SCHEMA.dummy_table_name_for_internal_testing", value,
"leading/trailing separator must be stripped, got: " + value);
}

@Test
void stampLabelValueIsKubernetesLabelValueCompliant() {
// K8s label values must match (([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?
Expand Down
Loading