QuerySnapshotYaml.java

package li.selman.persistencetest.snapshot;

/**
 * Renders a {@link QuerySnapshot} as deterministic YAML text.
 *
 * <p>Hand-written rather than delegated to a general-purpose YAML library: the schema is small and fixed
 * (a list of four-field entries), and a general library's own formatting choices (key ordering, quoting,
 * scalar style) are one more source of non-determinism to control for no real benefit here. Multi-line SQL
 * uses YAML's block literal style ({@code |}), matching how a human would hand-write it.
 */
final class QuerySnapshotYaml {

    private QuerySnapshotYaml() {}

    static String render(QuerySnapshot snapshot) {
        if (snapshot.queries().isEmpty()) {
            return "queries: []";
        }
        StringBuilder yaml = new StringBuilder("queries:\n");
        for (QuerySnapshotEntry entry : snapshot.queries()) {
            yaml.append("  - type: ").append(entry.statementType()).append('\n');
            appendTables(yaml, entry.tables());
            appendNormalizedSql(yaml, entry.normalizedSql());
            yaml.append("    count: ").append(entry.count()).append('\n');
        }
        // No trailing newline: java-snapshot-testing strips it when persisting to the .snap file, so
        // keeping one here would make every freshly-rendered snapshot mismatch the file it's compared
        // against on the very next run.
        yaml.setLength(yaml.length() - 1);
        return yaml.toString();
    }

    private static void appendTables(StringBuilder yaml, java.util.List<String> tables) {
        if (tables.isEmpty()) {
            yaml.append("    tables: []\n");
            return;
        }
        yaml.append("    tables:\n");
        for (String table : tables) {
            yaml.append("      - ").append(table).append('\n');
        }
    }

    private static void appendNormalizedSql(StringBuilder yaml, String normalizedSql) {
        yaml.append("    normalizedSql: |\n");
        for (String line : normalizedSql.split("\n", -1)) {
            yaml.append("      ").append(line).append('\n');
        }
    }
}