Skip to content

ConnectionBase

Wyatt Greenway edited this page Oct 1, 2022 · 36 revisions

class ConnectionBase extends EventEmitter

ConnectionBase is the base class that all connection classes should inherit from. It provides common functionality to all connections, and converts literals and types into their native database representation.

A "connection" in Mythix ORM is essentially the "application" for the ORM. It stores all models used by the connection, stores and defines the query generator (if any), converts literals and types, and also provides the query engine.

Multiple connections can be used at the same time in Mythix ORM. It is also planned that someday Mythix ORM (or the community) will provide a multiplex connection, to mix multiple connections into a single connection for the entire application.

For now you can use multiple connections at once. Just know that you should read and fully understand Connection Binding if you plan on using more than one connection for your application.

ConnectionBase is also an Event Emitter, so you can bind events to a connection instance with .on, and unbind with .off. Events are connection specific, but common events that can be bound to are:

  1. connect - Commonly fired when a connection is successfully established
  2. acquire - Commonly fired when a connection is acquired from a connection pool
  3. error - Commonly fired when a database level error occurs
  4. disconnect - Commonly fired when a connection is disconnected

This is just an example of common connection driver events. Please see documentation for your specific database connection for the proper events.

static property ConnectionBase::_isMythixConnection: boolean

Helper for type checking methods. Should always be true.


property ConnectionBase::dialect: string

The dialect of the database, i.e. 'sqlite', or 'postgresql'.


static property ConnectionBase::Literals: Literals

All default Mythix ORM literal classes, provided for convenient access.


method ConnectionBase::buildConnectionContext(connection?: Connection = this): Map<any, any>

This builds a "connection context" to provide to the AsyncLocalStorage context of a Connection.createContext call.

By default, this will set a connection property on the context, which will be the value of this connection instance. It also sets a connection property on the sub-contexts for each model. This is because models might have different connections, and so need a context per-model to work properly.

"How could a model have different connections?" you ask? Well, it probably won't. But being as this is an AsyncLocalStorage context, it provides the connection to every model inside the context. Your application might be using other models that aren't part of this connection, and we wouldn't want those to get the wrong connection for those models.

Arguments:

  • connection?: Connection (Default: this)

    The connection to create the context for. This can be provided, and is used in place of this instance, for example, in the case of transactions. Transactions generally are the "same" connection, but not the same instance.

Return value: Map<any, any>

The new context that will be used for Connection.createContext.


method ConnectionBase::constructor(options: object): Connection

Create a connection.

The options argument is generally connection specific. However, there are a few generic options, which you will find listed in the table below:

Option Type Default Value Description
bindModels boolean true If true, then bind the provided models to this connection. Models are bound to a connection by setting a static _mythixBoundConnection property on each model class to this connection instance.
forceConnectionBinding boolean false Normally attempting to bind a connection to a model more than once will result in an exception being thrown. However, if you set this property to true, then Mythix ORM will rebind the connection without complaint, even if a connection is already bound to your models. Make sure you know what you are doing if you use this option.
models Array or Object of Models undefined Models to provide to this connection. This can be either an array of Models, or an Object where each value is a Model
QueryEngine class QueryEngine QueryEngine The QueryEngine class to use for this connection and all this connection's models. You can provide your own class if you wish to add onto the query interface.
queryGenerator QueryGenerator Connection specific The query generator for this connection. If a QueryGenerator instance is provided (the correct one for the connection you are using), then this provided query generator will be used. If one isn't provided, then the connection will create its own query generator that is specific to the connection type.

Arguments:

  • options: object

    Connection specific options to supply to your connection. These will commonly include things like a hostname to connect to, a user name and password, and any connection specific parameters.

Return value: Connection


method ConnectionBase::createContext(callback: async Function, connection?: Connection = this, thisArg?: any = this): any

Create a connection context to serve all code running inside it this connection.

This uses AsyncLocalStorage to create a context that is passed through the entire call stack of the callback. In this way, a connection can be provided to every model and every operation within the call.

Arguments:

  • callback: async Function

    The method to provide the context to. Every call inside this call stack will be provided the connection.

  • connection?: Connection (Default: this)

    The connection to provide. Generally this will just be this connection instance, however, it can be specified, and is for example inside transactions.

  • thisArg?: any (Default: this)

    The this value to provide to the given callback.

Return value: any

The return value of the given callback.


method ConnectionBase::findModelField(finder: Function): Field | undefined

Find a specific field across all registered models.

This method is similar to Array.find, except that the arguments to this finder method are those provided by Model.iterateFields. If this finder method returns a truthy value for a given field, then that is the field that will be returned.

Notes:

  • This will search for the field across all models registered to the connection. To find a specific field for a known model use Connection.getField instead.

Arguments:

  • finder: Function

    A function to assist in finding the specified field. The signature for this function must match that used by Model.iterateFields.

Return value: Field | undefined

The field found, if any.


method ConnectionBase::getContextValue(key: any, defaultValue?: any): any

Get a value from the AsyncLocalStorage context.

AsyncLocalStorage is used primarily for two purposes: 1) to provide a connection to models, and 2) to pass a transaction connection down through the call stack. However, it can also be used for any "context" level values the user wishes to store.

Notes:

  • An AsyncLocalStorage context might not exist when this call is made, in which case this method will return undefined, or the defaultValue if any was provided.

Arguments:

  • key: any

    The key for the value you wish to fetch. The underlying "context" provided by AsyncLocalStorage is a Map, so the "key" can be any value.

  • defaultValue?: any

    The default value to return if there is no current AsyncLocalStorage context, or if the requested key is not found.

Return value: any


method ConnectionBase::getDefaultOrder(Model: class Model, options: object): Array<string>

Get the default order for selecting rows from the database. This will call the Model's Model.defaultOrder method first to see if the model specifies a default order for itself. If it doesn't, then the connection driver itself might specify a default order for each table.

Arguments:

  • Model: class Model

    The model/table to fetch the default order for.

  • options: object

    Operation specific options (i.e. options for a "select" call)

Return value: Array<string>

An array of fully qualified field names for this model should be returned by this method. An empty array, null, or undefined are also valid return values (in which case no order will be applied to the given operation).


method ConnectionBase::getLockMode(options: any): object

This method is an internal method that parses the "lock mode" options passed to a call to Connection.transaction.

These might be different depending on the connection driver you are using. Please refer to the documentation for your connection driver for more details.

Arguments:

  • options: any

    Possibly connection specific lock options for a connection's Connection.transaction method. Generally this will either be a true value, a Model name (for which table to lock), or a complete lock options object, which generally will look something like: { lock: boolean; modelName: string; read: boolean; write: boolean }

    lock - If true, then lock the transaction
    modelName - The name of the table(s) to lock
    read - If true, then lock for reads
    write - If true, then lock for writes.

Return value: object

Return the lock options for a transaction. These might change based on the connection driver you are using, but will generally look like { lock: boolean; modelName: string; read: boolean; write: boolean }.

  1. lock - If true, then lock the transaction
  2. modelName - The name of the table(s) to lock
  3. read - If true, then lock for reads
  4. write - If true, then lock for writes.

method ConnectionBase::getOptions(): object

Get the options for this connection.

These will be the options provided to the connection during creation, plus any other options the connection driver itself internally sets.

Return value: object

The options for this connection.


method ConnectionBase::isLimitSupportedInContext(options: object): boolean

This method is called (and often provided) by the underlying database driver to see if a LIMIT clause is allowed to appear in a given context/operation.

Arguments:

  • options: object

    Driver specific options for the context.

Return value: boolean


method ConnectionBase::isOrderSupportedInContext(options: object): boolean

This method is called (and often provided) by the underlying database driver to see if an ORDER BY clause is allowed to appear in a given context/operation.

Arguments:

  • options: object

    Driver specific options for the context.

Return value: boolean


method ConnectionBase::isStarted(): boolean

Check to see if start has already been called on this connection. This is used to know if a connection is "active" or not.

Return value: boolean


method ConnectionBase::parseQualifiedName(fieldName: string): object

This is simply a convenience method that calls ModelUtils.parseQualifiedName.

Arguments:

Return value: object

The result. See ModelUtils.parseQualifiedName for more information.

See also: ModelUtils.parseQualifiedName


method ConnectionBase::registerModel(Model: class Model, options?: object): class Model

Register the provided model class.

This will register the provided model class with this connection. The model must not already be bound to another connection, or you must specify the option { forceConnectionBinding: true } if it is. You can specify the option of { bindModels: false } if you don't wish to bind this model to this connection.

Any options provided are optional, and will override the same options provided to the connection itself when it was created.

Arguments:

  • Model: class Model

    The model class to register with this connection. If not bound, then it will simply exist in the model pool for this connection. If bound, then this connection will bind itself to the model being registered.

  • options?: object

    Options looks like { forceConnectionBinding: boolean; bindModels: boolean; }. This is an optional argument. Both options will default to the same options provided to the connection when it was created. If you specify either of these options they simply override the connection's default.

Return value: class Model

The registered model class, which may have changed during registration. It is not uncommon for the connection driver itself to modify the model class, or to return a new model class that inherits from your model class. The class that is returned should be the class that you use for this connection, and will be the same class returned by a call to Connection.getModel, or Connection.getModels.


method ConnectionBase::registerModels(Model: Array<class Model> | { [key: string]: class Model }, options?: object): class Model

Register multiple models at the same time.

This will register the provided models with this connection. The models provided must not already be bound to another connection, or you must specify the option { forceConnectionBinding: true } if any of them are. You can specify the option of { bindModels: false } if you don't wish to bind these models to this connection.

Any options provided are optional, and will override the same options provided to the connection itself when it was created.

Arguments:

  • Model: Array<class Model> | { [key: string]: class Model }

    The model classes to register with this connection. If no models are bound, then they will simply exist in the model pool for this connection. If bound, then this connection will bind itself to every model being registered.

  • options?: object

    Options looks like { forceConnectionBinding: boolean; bindModels: boolean; }. This is an optional argument. Both options will default to the same options provided to the connection when it was created. If you specify either of these options they simply override the connection's default.

Return value: class Model

The registered model classes, which may have changed during registration. It is not uncommon for the connection driver itself to modify the model classes, or to return a new model classes that inherit from your model classes. The classes that are returned should be the classes that you use for this connection, and will be the same classes returned by a call to Connection.getModel, or Connection.getModels.


method ConnectionBase::setContextValue(key: any, value: any): any

Set a value onto the AsyncLocalStorage context.

AsyncLocalStorage is used primarily for two purposes: 1) to provide a connection to models, and 2) to pass a transaction connection down through the call stack. However, it can also be used for any "context" level values the user wishes to store.

Notes:

  • An AsyncLocalStorage context might not exist when this call is made, in which case this method will do nothing, and silently return.

Arguments:

  • key: any

    The key for the value you wish to set. The underlying "context" provided by AsyncLocalStorage is a Map, so the "key" can be any value.

  • value: any

    The value to set to the specified key.

Return value: any


static method ConnectionBase::getLiteralClassByName(name: string): class LiteralBase

Fetch a literal class by its name.

The following is a table that displays the name argument that can be provided, and the resulting Literal class that would be returned for that name.

name Resulting literal class
'Average' AverageLiteral
'Base' LiteralBase
'Count' CountLiteral
'Distinct' DistinctLiteral
'Field' FieldLiteral
'FieldBase' LiteralFieldBase
'Literal' Literal
'Max' MaxLiteral
'Min' MinLiteral
'Sum' SumLiteral

Arguments:

  • name: string

    The name of the literal class to return.

Return value: class LiteralBase

Return the literal class requested.


static method ConnectionBase::isConnection(value: any): boolean

Check to see if the provided value is an instance of a Mythix ORM ConnectionBase. Unlike ConnectionBase.static isConnectionClass, which checks if a class is a ConnectionBase, this will check to see if an instance is an instance of a Mythix ORM ConnectionBase. It will return true if the provided value is an instanceof ConnectionBase, or if the value's constructor property has a truthy _isMythixConnection property (value.constructor._isMythixConnection)

Arguments:

  • value: any

    Value to check.

Return value: boolean


static method ConnectionBase::isConnectionClass(value: Function): boolean

Use this method to check if a class is a Mythix ORM connection. It will return true if the provided value is a class that inherits from ConnectionBase, or if the provided value has an attribute named _isMythixConnection that is truthy.

Arguments:

  • value: Function

    Value to check.

Return value: boolean


static method ConnectionBase::Literal(name: string): LiteralBase

Create the literal specified by name.

Whereas ConnectionBase.static getLiteralClassByName will simply return the literal class specified, this will create the specified literal, with the provided arguments.

Please see ConnectionBase.static getLiteralClassByName for possible names that can be provided as the name argument.

Arguments:

Return value: LiteralBase

Return an instance the literal requested, using the arguments specified.

See also: static ConnectionBase.getLiteralClassByName


method ConnectionBase::toQueryEngine(value: any): QueryEngine | undefined

This will take something that can be turned into a query and turn it into a query.

If a QueryEngine instance is provided, it will simply be returned.

If a Model is provided, then Model.where will be returned, returning a QueryEngine for the model provided.

In the future this may also accept other possible values that could be turned into a query.

This is often internally called by methods of the connection on a given argument provided by the user, which could validly be either a model or a query. Connection.destroyAll is one example of this.

Arguments:

  • value: any

    The value to attempt to turn into a QueryEngine.

Return value: QueryEngine | undefined



Clone this wiki locally