How Ossie Converters Handle Dialect-Specific Transformations: GoodData, Salesforce, and dbt
Ossie stores expressions in a dialect-aware structure where each converter selects, translates, or falls back between SQL dialects like ANSI_SQL, MAQL, SNOWFLAKE, and BIGQUERY based on the target platform's requirements.
The apache/ossie repository provides a framework for converting analytics assets between platforms. Handling dialect-specific transformations requires careful management of SQL syntax variations across data warehouses. Ossie solves this through a dual-layer expression model that allows converters to emit dialect-appropriate code while maintaining fallback options.
Understanding Ossie's Dialect-Aware Expression Model
Ossie represents field expressions using an OSIExpression object that contains a list of OSIDialectExpression objects. Each dialect expression pairs a concrete SQL fragment with its specific dialect identifier, such as ANSI_SQL, MAQL, SNOWFLAKE, or BIGQUERY. This structure enables converters to store multiple dialect variants of the same logical expression and select the appropriate variant during conversion.
When processing a conversion, each converter implements three critical behaviors: discovering the target dialect, creating or selecting the dialect-specific expression, and handling cases where a dialect is unsupported.
GoodData Converter: Dual-Dialect MAQL and ANSI_SQL Handling
The GoodData converter operates on a fixed two-dialect model. It always produces both ANSI_SQL (representing the source column) and MAQL (GoodData's analytical query language) when converting assets.
Converting from Ossie to GoodData
When transforming Ossie fields into GoodData assets, the converter extracts the ANSI_SQL dialect expression from the source field to determine the underlying column reference. In converters/gooddata/src/ossie_gooddata/osi_to_gooddata.py, the _get_source_column function iterates through the dialect list to locate the ANSI-compliant fragment:
# converters/gooddata/src/ossie_gooddata/osi_to_gooddata.py
def _get_source_column(field_def: dict[str, Any]) -> str:
for dialect_expr in field_def.get("expression", {}).get("dialects", []):
if dialect_expr.get("dialect") == "ANSI_SQL":
return dialect_expr["expression"]
return field_def["name"]
If the source field only contains an ANSI_SQL fragment, the converter generates the corresponding MAQL expression on-the-fly using the _detect_type_from_maql logic to determine whether to wrap the identifier as a {label/...} or {fact/...} reference.
Converting from GoodData to Ossie
During the reverse conversion in converters/gooddata/src/ossie_gooddata/gooddata_to_osi.py, the converter constructs an OSIExpression containing both dialects. It prefers the MAQL expression when present, otherwise falling back to the ANSI_SQL representation:
# converters/gooddata/src/ossie_gooddata/gooddata_to_osi.py (excerpt)
dialects = [
{"dialect": "ANSI_SQL", "expression": attr.source_column},
{"dialect": "MAQL", "expression": f"{{label/{dataset_id}.{attr.id}}}"},
]
This dual-storage approach ensures that round-trip conversions preserve both the analytical semantics (MAQL) and the underlying data access patterns (ANSI_SQL).
Salesforce Converter: Connection-Driven Dialect Resolution
Unlike GoodData's fixed dialect pair, the Salesforce converter resolves dialects dynamically based on connection metadata defined in the export configuration.
Building the Dialect Index
The converter constructs a dialect index that maps each Salesforce connection ID to an OSIDialect enum value. In converters/salesforce/src/main/java/org/apache/ossie/converter/pipeline/PipelineConfigLoader.java, the _buildDialectIndex method processes the connections array:
// converters/salesforce/src/main/java/org/apache/ossie/converter/pipeline/PipelineConfigLoader.java
private Map<String, OSIDialect> _buildDialectIndex(Map<String, Object> export, List<ConverterIssue> issues) {
Map<String, OSIDialect> index = new HashMap<>();
for (Map<String, Object> connection : (List<Map<String, Object>>) export.get("connections")) {
String name = (String) connection.get("dialect");
OSIDialect dialect = _DIALECT_MAP.getOrDefault(name.toLowerCase(), OSIDialect.ANSI_SQL);
index.put((String) connection.get("connection_id"), dialect);
}
return index;
}
The _DIALECT_MAP translates Salesforce connection dialect strings (e.g., "snowflake", "bigquery") into Ossie's internal dialect enumeration.
Emitting Dialect-Specific Expressions
When converting sheets in converters/salesforce/src/main/java/org/apache/ossie/converter/ConverterImpl.java, the _makeExpression helper wraps raw expressions with their resolved dialect:
// converters/salesforce/src/main/java/org/apache/ossie/converter/ConverterImpl.java
private OSIExpression _makeExpression(String expression, OSIDialect dialect) {
return new OSIExpression(List.of(new OSIDialectExpression(dialect, expression)));
}
If the connection's dialect has no OSSIE equivalent, the converter substitutes the expression as ANSI_SQL and records a ConverterIssueType.UNSUPPORTED_DIALECT warning in the issues log. This ensures the conversion completes while alerting users to potential semantic mismatches.
dbt Converter: Target-Dialect Instantiation
The dbt converter takes a different approach by binding to a specific target dialect at instantiation time. This determines how identifiers, quoting, and filter syntax render throughout the generated manifest.
Dialect-Specific Rendering and Quoting
In converters/dbt/src/ossie_dbt/osi_to_msi.py, the converter stores the target dialect in its constructor:
# converters/dbt/src/ossie_dbt/osi_to_msi.py
def __init__(self, dialect: OSIDialect = OSIDialect.ANSI_SQL) -> None:
self._dialect = dialect
The MSIToOSIConverter.convert method then utilizes helper functions in converters/dbt/src/ossie_dbt/expression_utils.py to render dialect-appropriate syntax. For example, the quote_identifier function applies platform-specific quoting rules:
# converters/dbt/src/ossie_dbt/expression_utils.py
def quote_identifier(name: str, dialect: OSIDialect) -> str:
if dialect == OSIDialect.SNOWFLAKE:
return f'"{name}"' # Snowflake uses double quotes
if dialect == OSIDialect.BIGQUERY:
return f"`{name}`" # BigQuery uses back‑ticks
return name # ANSI_SQL leaves it unchanged
When the chosen dialect is not explicitly supported by the dbt manifest, the converter falls back to ANSI_SQL and emits a warning through the ConverterIssue mechanism. This default ensures that generated dbt models remain executable even when specific warehouse features are unavailable.
Summary
- Ossie uses a dialect-aware expression model where each OSIExpression contains multiple OSIDialectExpression objects paired with specific dialects like
ANSI_SQL,MAQL,SNOWFLAKE, andBIGQUERY. - The GoodData converter maintains a dual-dialect approach, extracting
ANSI_SQLfor source columns and generatingMAQLfor analytical expressions, with fallback to ANSI when MAQL is absent. - The Salesforce converter dynamically resolves dialects from connection metadata using
_buildDialectIndex, emitting expressions verbatim for supported dialects or substitutingANSI_SQLwith anUNSUPPORTED_DIALECTwarning. - The dbt converter instantiates with a target dialect (defaulting to
ANSI_SQL) and uses utility functions likequote_identifierinexpression_utils.pyto render dialect-specific syntax, falling back to ANSI when the target is unsupported.
Frequently Asked Questions
What happens when a converter encounters an unsupported dialect?
The converter substitutes the expression using ANSI_SQL as the fallback dialect and logs a ConverterIssueType.UNSUPPORTED_DIALECT warning. This approach ensures the conversion completes without data loss while alerting users to potential syntax incompatibilities.
How does the GoodData converter handle missing MAQL expressions?
When converting from GoodData to Ossie, if the payload lacks a MAQL fragment, the converter simply returns the ANSI_SQL expression as the sole dialect in the resulting OSIExpression. During Ossie-to-GoodData conversion, if only ANSI_SQL is present, the converter generates the MAQL expression on-the-fly using type detection heuristics.
Can the dbt converter generate manifests for multiple dialects simultaneously?
No, the dbt converter is instantiated with a single target OSIDialect that determines quoting and syntax rules for the entire conversion. To generate manifests for multiple dialects, users must run separate conversion processes with different dialect parameters.
How does Ossie ensure data type compatibility across different SQL dialects?
Each converter includes dedicated mapping modules—such as datatype_mapping.py for GoodData and SalesforceDataTypeMapper.java for Salesforce—that translate Ossie's internal type system into platform-specific data types. These mappings handle dialect-specific type names while preserving semantic meaning across warehouses.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →