Target a different database
Sometimes the objects a template manages don't live in the database your connection points at, but in a sibling database on the same server. A typical setup: the connection targets the main application database, while a handful of stored procedures live in a separate reporting database that exists once per environment:
| Environment | Connection database | Where the procedures live |
|---|---|---|
| DEV | SALES_DEV_CORE | SALES_DEV_REPORTING |
| TEST | SALES_TEST_CORE | SALES_TEST_REPORTING |
| PROD | SALES_PROD_CORE | SALES_PROD_REPORTING |
You don't want a second connection per environment just for those objects, and you don't want USE [SALES_PROD_REPORTING] baked into a script that must also deploy to TEST.
The Database attribute solves this: the template declares a rule for deriving the target database from the connection's database, DataStar resolves it at runtime, and the resolved name never appears in the generated script.
The Database attribute is supported on SQL Server connections only. On Oracle the override is ignored with a warning (schemas play this role on Oracle).
The attribute
Valid on the root element of both object components and data components:
<ObjectComponent Schema="dbo" Category="reporting-procedures" Name="${filename}"
Database="$(ConnectionDatabase|replace(_CORE,_REPORTING))">
<SchemaObject Name="${name}" Type="Procedure"/>
...
</ObjectComponent>
Connected to SALES_PROD_CORE, the expression resolves to SALES_PROD_REPORTING; connected to SALES_TEST_CORE, it resolves to SALES_TEST_REPORTING. A new environment that follows the naming convention needs no template changes at all.
Expression syntax
The attribute value is a template string: literal text freely mixed with $(...) tokens. A token is a source followed by zero or more pipe-separated transforms, applied left to right:
$(ConnectionDatabase|transform|transform|...)
ConnectionDatabase (the database of the active connection) is the only source. $$ escapes a literal dollar sign.
| Transform | Effect |
|---|---|
replace(find,repl) | Literal find/replace, case-insensitive. |
regex(pattern,repl) | .NET regular-expression replace; supports $1 capture groups. |
part(delim,index) | Split on a delimiter and take one segment. Negative index counts from the end (-1 is the last segment). |
upper / lower | Invariant upper/lower casing. |
Transform arguments are trimmed, so replace(_CORE, _REPORTING) and replace(_CORE,_REPORTING) are equivalent.
Examples
All examples assume the connection database is SALES_TEST_CORE.
| Expression | Resolves to | Notes |
|---|---|---|
| (omitted) | SALES_TEST_CORE | No override; the connection's own database. |
SharedReference | SharedReference | Literal name, same in every environment. |
$(ConnectionDatabase|replace(_CORE,_REPORTING)) | SALES_TEST_REPORTING | The suffix-swap convention. |
$(ConnectionDatabase|regex(_CORE$,_REPORTING)) | SALES_TEST_REPORTING | Anchored, so a _CORE mid-name is left alone. |
$(ConnectionDatabase|part(_,0))_$(ConnectionDatabase|part(_,1))_REPORTING | SALES_TEST_REPORTING | Rebuild the name from segments. |
$(ConnectionDatabase|replace(_CORE,_REPORTING)|lower) | sales_test_reporting | Transforms chain left to right. |
What the override applies to
Once declared, the override is honoured everywhere the template touches the database:
- Extraction. Object and data scripts are generated from the target database. The connection is switched server-side for the duration of generation and restored afterwards.
- Dynamic queries. The template's
<DynamicQuery>runs against the target database, so component discovery, the component grid, and variable hydration all reflect the right objects. - Deployment. The deploying session re-resolves the expression against its own connection database and switches context before executing the script, inside the deployment transaction. Deploying the same package to TEST and PROD targets
SALES_TEST_REPORTINGandSALES_PROD_REPORTINGrespectively, from one script file.
The generated script itself stays environment-neutral: no USE statement, no database name (unless you explicitly opt into IncludeDatabaseContext, which defeats the purpose here).
Failure behaviour
Resolution fails loudly rather than silently scripting the wrong database. If the expression can't be parsed, resolves to an empty string, or names a database that doesn't exist on the server, the error reports the expression, the connection database, and the resolved name. A connection that breaks the naming convention (say SALES_SANDBOX) surfaces immediately as:
Failed to switch to database 'SALES_SANDBOX' (resolved from
'$(ConnectionDatabase|replace(_CORE,_REPORTING))' against 'SALES_SANDBOX')
(replace with no match is an identity, so the unmatched name passes through and fails at the existence check.)
Caveats
- Permissions. The connection's login needs appropriate rights in the target database: read access for extraction, DDL/DML rights for deployment.
- No component variables. The expression cannot reference
${...}component variables when the template has a<DynamicQuery>- the variables are produced by that query, which has to know its target database first. Stick to$(ConnectionDatabase)tokens and literals. - One database per template. The override is template-scoped. If you have objects in two sibling databases, give each its own template (and its own
Category, which keeps them visually distinct in the UI anyway).
See also
- Object component schema: full attribute reference.
- Data component schema: full attribute reference.
- Generate components in bulk: dynamic queries, which run against the overridden database.