Special characters in database names¶
Since 0.3.1.209, tdfs4ds works when the feature-store database has a name that
is not a bare-legal Teradata identifier — SVC@CORP, my-user, DEINF.CARLOSN,
jean dupont, josé.
You do not have to do anything to turn this on. If the name needs quotes, tdfs4ds quotes it; if it does not, nothing changes.
Why it comes up¶
A Teradata object name can be written without quotes only when it matches
[A-Za-z][A-Za-z0-9_$#]*. Anything else has to be a double-quoted
identifier:
CREATE TABLE SVC@CORP.FS_FEATURE_CATALOG -- syntax error
CREATE TABLE "SVC@CORP".FS_FEATURE_CATALOG -- valid
This is not an exotic case, because the logon user is usually a database of the
same name and tdfs4ds.SCHEMA defaults to the session's database:
An LDAP or Active Directory login (first.last@company, svc-ingest) lands
there directly.
What you write¶
Nothing special. Pass the name as it is — unquoted, exactly as you would a normal one:
tdfs4ds.SCHEMA keeps holding the raw name, because that is what a
connection parameter, a teradataml keyword argument and a DBC predicate all
need. Two accessors give the SQL form when you need to build a statement
yourself:
tdfs4ds.SCHEMA # 'SVC@CORP' - raw
tdfs4ds.schema_sql() # '"SVC@CORP"' - identifier form
tdfs4ds.view_schema_sql() # same, for the view database
Building your own SQL against the store¶
If you write SQL by hand — a source view for upload_features, an ad-hoc query —
qualify names with the helpers rather than an f-string:
from tdfs4ds.utils.identifiers import qualified, split_qualified, quote_ident
qualified("SVC@CORP", "claims_raw") # '"SVC@CORP".claims_raw'
qualified("TDB", "claims_raw") # 'TDB.claims_raw' (unchanged)
quote_ident("SVC@CORP") # '"SVC@CORP"'
split_qualified('"SVC@CORP"."claims_raw"') # ('SVC@CORP', 'claims_raw')
Only the half that needs quoting gets quoted, so ordinary names read exactly as before.
Quote identifiers, not literals
The two look similar and behave very differently. A DBC predicate compares
the name as data, so it takes the raw name in single quotes. Putting a
double-quoted identifier there makes Teradata read it as a column reference
and the query silently matches nothing:
WHERE DatabaseName = 'SVC@CORP' -- correct: a string literal
WHERE DatabaseName = "SVC@CORP" -- wrong: reads as a column name
Likewise, never pre-quote a name you hand to teradataml
(in_schema(), copy_to_sql(schema_name=…), db_list_tables(schema_name=…))
or to create_context(). Those quote it themselves, or want a literal.
What is covered¶
The whole core path is, and it has been verified end to end against a live
Vantage 20 database called "FS@TEST":
setup()/connect()and every catalog they createupload_features(),run(), segmented ingestion with aFilterManagerTimeManagerandFilterManagerbacking tables and viewsbuild_dataset()and the dataset catalog- the business dictionary and
document_* - the persisted lineage graph, including edges resolved through the quoted database
What is not covered yet¶
setup() and connect() log this list when they detect a name that needs
quoting, so you are told up front rather than meeting it later:
| Area | Status |
|---|---|
| Teradata Enterprise Vector Store backend | Not supported. It bakes the source name into a collection view. Use VECTOR_STORE_BACKEND='chroma' for the consumer agent's index, or keep the store in a database with an ordinary name. |
Benchmark runner (tdfs4ds.run_benchmark) |
Not covered. |
Cross-store migration (plan_migration / migrate_objects) |
Not covered. |
| A hyphen in the name, for lineage only | The name is quoted correctly in generated SQL, but the lineage DDL scanner does not resolve it: a hyphen is the SQL minus operator and begins a -- comment, so it cannot be matched unambiguously there. @, $, #, . and spaces are fine. |
Compatibility¶
A database whose name needs no quoting generates byte-identical SQL to
earlier versions — not merely equivalent SQL. This is asserted in
tests/test_quoted_identifiers.py, which captures every statement the
store-creation path emits and compares the two forms. Existing stores are
unaffected, and nothing needs migrating.