Class DataSourceRegistry
- All Implemented Interfaces:
ConnectionProvider
DataSource handles, so a
program can hand the engine a database it already has open.
The AST models a connection declaratively — a name, a connector type and a
property map — and the engine's own modules cannot name java.sql at
all. A live handle therefore cannot ride in the AST, and does not need to:
the AST names the connection and this registry maps that name to the
handle, the same shape PlanEstimates uses to sit beside a plan
rather than on it.
It is a ConnectionProvider, so it drops into both places that need a
connection. A name it does not hold is delegated to
ConnectionProvider.FROM_URL, which is what lets one session mix
injected handles with connections a script declares in the ordinary way.
Why a DataSource and not a Connection
A single Connection is not accepted, including as a convenience.
The JDBC connector's row stream is lazy over a live ResultSet and holds
its connection until the stream closes, so any join with both sides on one
source opens two scans concurrently: one connection would either serialize or
corrupt them. The failure would appear on the first join, long after the call
site that chose it. A DataSource hands out as many as the query needs
and does its own pooling — which is why managesPooling(com.darkcollective.relix.lang.ast.ConnectionDeclaration) is true
for every registered name, and releasing closes rather than retaining.
Dialect
ConnectionDeclarations normally get their dialect from a declared
dialect: or from the JDBC URL, and an injected handle has neither. It
is read instead from DatabaseMetaData.getDatabaseProductName()
— once per name, memoized, because it costs a connection. Getting it wrong
costs pushdown, never correctness, so a probe that fails is simply no answer
and the generic dialect applies.
Thread safety
Registration is expected during setup and lookup during execution; the maps are concurrent, so a late registration is safe but races with an in-flight query the way any late configuration change would.
-
Field Summary
Fields inherited from interface com.darkcollective.relix.connectors.std.internal.ConnectionProvider
FROM_URL -
Constructor Summary
ConstructorsConstructorDescriptionCreates an empty registry delegating unregistered names toConnectionProvider.FROM_URL.DataSourceRegistry(ConnectionProvider fallback) Creates an empty registry delegating unregistered names tofallback. -
Method Summary
Modifier and TypeMethodDescriptionconnectionFor(ConnectionDeclaration connection) Opens a connection for the given declaration.declarationFor(String name) Builds theConnectionDeclarationthat namesnameto the engine, carrying the resolved dialect so the planner reaches the same answer it would for a declared connection.dialectFor(String name) The dialect token forname: the one registered explicitly, else one read from the database's own metadata, else empty.booleanReturns whethernameis bound to a handle here.booleanmanagesPooling(ConnectionDeclaration connection) Whether connections this provider returns forconnectionare pooled by something other thanConnectionPool, so the engine must not retain them.register(String name, DataSource dataSource) BindsnametodataSource, replacing any previous binding.register(String name, DataSource dataSource, String dialect) BindsnametodataSourcewith an explicit dialect, skipping the metadata probe.
-
Constructor Details
-
DataSourceRegistry
public DataSourceRegistry()Creates an empty registry delegating unregistered names toConnectionProvider.FROM_URL. -
DataSourceRegistry
Creates an empty registry delegating unregistered names tofallback.- Parameters:
fallback- the provider for names this registry does not hold; must not be null
-
-
Method Details
-
register
BindsnametodataSource, replacing any previous binding.- Parameters:
name- the connection name as the script or session spells it; must not be blankdataSource- the live handle; must not be null- Returns:
- this registry, for chaining
-
register
BindsnametodataSourcewith an explicit dialect, skipping the metadata probe.- Parameters:
name- the connection name; must not be blankdataSource- the live handle; must not be nulldialect- the dialect token (e.g."postgres"); must not be null- Returns:
- this registry, for chaining
-
holds
Returns whethernameis bound to a handle here.- Parameters:
name- the connection name- Returns:
- whether this registry serves that name
-
connectionFor
Description copied from interface:ConnectionProviderOpens a connection for the given declaration.- Specified by:
connectionForin interfaceConnectionProvider- Parameters:
connection- the declared connection; must not be null- Returns:
- an open connection the caller owns
- Throws:
SQLException- if no connection can be opened for this declaration
-
managesPooling
Description copied from interface:ConnectionProviderWhether connections this provider returns forconnectionare pooled by something other thanConnectionPool, so the engine must not retain them.- Specified by:
managesPoolingin interfaceConnectionProvider- Parameters:
connection- the declared connection- Returns:
trueto bypass engine-side pooling;falseby default
-
dialectFor
The dialect token forname: the one registered explicitly, else one read from the database's own metadata, else empty.The probe opens a connection, so it runs once per name and its answer — including "could not tell" — is remembered.
- Parameters:
name- the connection name- Returns:
- the dialect token, or empty when unknown
-
declarationFor
Builds theConnectionDeclarationthat namesnameto the engine, carrying the resolved dialect so the planner reaches the same answer it would for a declared connection.It carries no
url: there is none, and that is the case theConnectionProviderseam exists to make representable.- Parameters:
name- the connection name; must be registered- Returns:
- the declaration to install in a session
- Throws:
IllegalArgumentException- if no handle is bound to that name
-