Server side repository. Override ServerRepository#select method return initialized TubDataStore
Usually is created by using one of the fabric functions:
- UB.Repository for entities from this server instance
- conn.Repository for access remote UB server
let store = UB.Repository('my_entity')
.attrs('id')
.where('code', 'in', ['1', '2', '3']) // code in ('1', '2', '3')
.where('name', 'contains', 'Homer') // name like '%homer%'
.where('birtday', 'geq', new Date()) //(birtday >= '2012-01-01')
.where('birtday', 'leq', new Date() + 10) // AND (birtday <= '2012-01-02')
.where('[age] -10', '>=', {age: 15}, 'byAge') // (age + 10 >= 15)
.where('', 'match', 'myvalue') // perform full text search for entity (require fts mixin)
.logic('(([byStrfType]) OR ([bySrfKindID]))AND(dasdsa)')
.select()
# new ServerRepository ()
Members
# UBQLv2 : boolean instance
Server side support UBQL v2 version (value in whereList)
# WhereCondition : string instance
Enumeration of all condition types. This enumeration defines a set of String values. It exists primarily for documentation purposes - in code use the actual string values like '>', don't reference them through this class like WhereCondition.more.
We define several aliases for the same condition. In case of direct HTTP request (without Repository) use only
non-aliased values (i.e. more
instead of '>' or 'gt')
Name | Type | Description |
---|---|---|
gt | string | Alias for more |
">" | string | Alias for more |
more | string | Greater than |
lt | string | Alias for less |
"<" | string | Alias for less |
less | string | Less than |
eq | string | Alias for equal |
"=" | string | Alias for equal |
equal | string | Equal to |
ge | string | Alias for moreEqual |
geq | string | Alias for moreEqual |
">=" | string | Alias for moreEqual |
moreEqual | string | Greater than or equal |
le | string | Alias for lessEqual |
leq | string | Alias for lessEqual |
"<=" | string | Alias for lessEqual |
lessEqual | string | Less than or equal |
ne | string | Alias for notEqual |
neq | string | Alias for notEqual |
"<>" | string | Alias for notEqual |
"!=" | string | Alias for notEqual |
"!==" | string | Alias for notEqual |
notEqual | string | Not equal |
contains | string | Alias for like |
like | string | Like condition. For attributes of type String only |
notContains | string | Alias for notLike |
notLike | string | Not like condition. For attributes of type String only |
isNull | string | Is null |
null | string | Alias for isNull |
notNull | string | Alias for notIsNull |
notIsNull | string | Not is null |
isNotNull | string | Alias for notIsNull |
isFalse | string | Is false, for attributes of type 'Boolean' only |
isTrue | string | Is true, for attributes of type 'Boolean' only |
beginWith | string | Alias for startWith |
startWith | string | Start with. For attributes of type String only |
startsWith | string | Alias for startWith |
startswith | string | Alias for startWith |
notBeginWith | string | Alias for notStartWith |
notStartWith | string | Not start with. For attributes of type String only |
notStartsWith | string | Alias for notStartWith |
includes | string | Alias for in |
in | string | One of. Can accept array of string on array of Int/Int64 as values depending on attribute type. |
notIncludes | string | Alias for notIn |
notIn | string | Not one of. See WhereCondition.in for details |
match | string | For entities with FTS mixin enabled. TODO - expand |
subquery | string | Execute a sub-query passed in values. Better to use 'in' condition with Repository as a values parameter or a CustomRepository.exists method |
exists | string | Execute a exists(sub-query) passed in values. Better to use CustomRepository.exists method |
notExists | string | Execute a not exists(sub-query) passed in values. Better to use CustomRepository.notExists method |
custom | string | Custom condition. For Server-side call only. For this condition expression can be any SQL statement |
Methods
# attrs (attrs: string) → CustomRepository instance
Adds attribute(s) or expression(s).
Can take expression as a field. In this case entity attribute name must be wrapped into [] brackets. In case of client-side execution the only valid expression is one of:
- 'SUM', 'COUNT', 'AVG', 'MAX', 'MIN', 'CAST', 'COALESCE'
// chaining
UB.Repository('uba_user').attrs('ID').attrs('name', 'firstName').attrs('disabled').selectAsObject()
// calculate sum over some attribute
UB.Repository('uba_user').attrs('SUM([disabled])').where('disabled', '=', true).selectScalar()
// In case of server-side execution any valid SQL expression is accepted by attr:
UB.Repository('uba_user').attrs('[ID] / 100 + 1').selectAsArray()
// JOIN `uba_userrole.roleID` is a attribute of type Entity. ORM choose `left join` in case attribute is `allowNull: true`
UB.Repository('uba_userrole').attrs(['userID', 'userID.name']).selectAsObject()
// todo Define a way to join for UNITY (@)
// get values for attribute of type MANY
UB.Repository('tst_maindata')
.attrs('ID', 'manyValue', 'manyValue.caption')
.where('code', '=', 'Code1')
.selectAsObject({'manyValue.caption': 'captions'})
// result is `[{"ID":331947938939292,"manyValue":"1,2","captions":"caption 10,caption 20"}]`
// Get attribute value for multi-language ("isMultiLang": true in meta file) attribute other when current session language
UB.Repository('org_employee').attrs(['ID', 'lastName_en^']).selectAsObject()
# attrsIf (addingCondition: *, attrs: string) → CustomRepository instance
Helper method for CustomRepository.attrs.
Calls attrs
in case addingCondition is truthy
Arguments:
let isPessimisticLock = !!UB.connection.domain.get('uba_user').attributes.mi_modifyDate
// with whereIf
let repo = UB.Repository('uba_user').attrs('ID').attrsIf(isPessimisticLock, 'mi_modifyDate')
//without whereIf
let repo = UB.Repository('uba_user').attrs('ID')
if (isPessimisticLock) repo = repo.attrs('mi_modifyDate')
# clearOrderList () → CustomRepository instance
Remove all sorting. This function mutates the current Repository
let repo1 = UB.Repository('uba_user').attrs('code', 'name).orderBy('name')
let repoWithoutOrder = repo1.clone().clearOrderList()
# clearWhereList () → CustomRepository instance
Remove all where conditions (except ones using in joinAs). This function mutates the current Repository
let repo1 = UB.Repository('uba_user').attrs('ID', 'code').where('ID', '>', 15, 'byID')
let repoWithoutWheres = repo1.clone().clearWhereList()
# clone () → CustomRepository instance
Creates a clone of this repository
let repo1 = UB.Repository('uba_user').attrs('ID', 'code').where('ID', '>', 15, 'byID')
let repo2 = repo1.clone()
repo1.orderBy('code')
repo2.attrs('name').where('ID', '>', 100, 'byID')
repo1.selectAsObject() // return ordered users with ID > 15
repo2.selectAsObject() // return unordered users with their names and ID > 100
# correlation (subQueryAttribute: string, masterAttribute: string, conditionopt: WhereCondition | string, clauseNameopt: string) → CustomRepository instance
If current repository is used as a sub-query for exists
, notExists
, in
or notIn
conditions
correlation with a master repository will added
# exists (subRepository: CustomRepository, clauseNameopt: string) → CustomRepository instance
Adds where condition with EXISTS
sub-query. Inside a sub-query there are two macros:
{master}
will be replaced by master entity alias{self}
will be replaced by sub-query entity alias
Arguments:
subRepository
: CustomRepositoryRepository, what represent a sub-query to be execute inside EXISTS statement
clauseName
: stringOptional clause name
UB.Repository('uba_user').attrs(['ID', 'name']) //select users
// who are not disabled
.where('disabled', '=', 0)
// which allowed access from Kiev
.where('trustedIP', 'in',
UB.Repository('geo_ip').attrs('IPAddr')
.where('city', '=', 'Kiev')
)
// who do not log in during this year
.notExists(
UB.Repository('uba_audit')
.correlation('actionUser', 'name') // here we link to uba_user.name
.where('actionTime', '>', new Date(2016, 1, 1))
.where('actionType', '=', 'LOGIN')
)
// but modify some data
.exists(
UB.Repository('uba_auditTrail')
.correlation('actionUser', 'ID') // here we link to uba_user.ID
.where('actionTime', '>', new Date(2016, 1, 1))
)
.select()
# groupBy (attr: string) → CustomRepository instance
Adds grouping
UB.Repository('my_entity').attrs('ID')
.groupBy('code')
UB.Repository('uba_user').attrs('disabled')
.groupBy('disabled').select()
UB.Repository('uba_user').attrs(['disabled','uPassword','COUNT([ID])'])
.groupBy(['disabled','uPassword']).select()
# join (whereItemName: string) → CustomRepository instance
Force where expressions
to be used in join part of SQL statement instead of where part. Applicable only for not cached entities
Arguments:
whereItemName
: stringname of where item to use in join.
// will generate
// SELECT A.ID, B.code FROM tst_document A LEFT JOIN tst_category B
// ON (B.instanceID = A.ID and B.ubUser = 10)
// instead of
// SELECT A.ID, B.code FROM tst_document A LEFT JOIN tst_category B
// ON B.instanceID = A.ID
// WHERE B.ubUser = 10
UB.Repository('tst_document').attrs(['ID', '[category.code]'])
.where('[category.ubUser]', '=', 10, 'wantInJoin')
.join('wantInJoin')
.selectAsObject().then(UB.logDebug)
# joinCondition (expression: string, condition: CustomRepository.WhereCondition, valuesopt: *, clauseNameopt: string) → CustomRepository instance
Adds join condition
Arguments:
expression
: stringAttribute name (with or without []) or valid expression with attributes in [].
condition
: CustomRepository.WhereConditionAny value from WhereCondition list.
values
: *Condition value. In case expression is complex can take {object} as value. In case values === undefined no values property passed to where list
clauseName
: stringOptional clause name to be used in {CustomRepository.logicalPredicates}. If not passed where will generate unique clause named 'c1', 'c2', ......
# limit (rowsLimit: number) → CustomRepository instance
How many rows to select. If 0 - select all rows started from .start()
Arguments:
rowsLimit
: number
// will return first two IDs from my_entity
let store = UB.Repository('my_entity').attrs('ID').limit(2).selectAsObject()
# logic (predicate: string) → CustomRepository instance
Arrange named where expressions
in logical order. By default, where expressions
are joined by AND logical predicate.
It is possible to join it in custom order using logic
.
Pay attention to condition name we pass as a 4-th parameter to .where()
Arguments:
predicate
: stringlogical predicate.
UB.Repository('my_entity').attrs('ID')
// code in ('1', '2', '3')
.where('code', 'in', ['1', '2', '3'], 'byCode')
// name like '%homer%'
.where('name', 'contains', 'Homer', 'byName')
//(birthday >= '2012-01-01') AND (birthday <= '2012-01-02')
.where('birthday', 'geq', new Date()).where('birthday', 'leq', new Date() + 10)
// (age + 10 >= 15)
.where('[age] -10', '>=', {age: 15}, 'byAge')
// (byCode OR byName) AND (all where items, not included in logic)
.logic('([byCode]) OR ([byName])')
# misc (flags: object) → CustomRepository instance
Apply miscellaneous options to resulting UBQL
Arguments:
flags
: object__mip_ondate
: DateSpecify date on which to select data for entities with
dataHistory
mixin. Default to Now()__mip_recordhistory
: booleanSelect only record history data for specified ID (for entities with
dataHistory
mixin)__mip_recordhistory_all
: booleanIgnore __mip_ondate and select all data (acts as select for entities without
dataHistory
mixin)__mip_disablecache
: booleanFor entities with cacheType in ["Session", "SessionEntity"] not check is data modified and always return result
__skipOptimisticLock
: booleanSkip optimistic lock for entities with
mStorage.simpleAudit = true
__allowSelectSafeDeleted
: booleanInclude softly deleted rows to the result
__useReplica
: booleanPrefer to use DB replica for select statement (if configured, EE only)
__skipSelectAfterUpdate
: booleanServer-side only
__skipSelectAfterInsert
: booleanServer-side only
__skipSelectBeforeUpdate
: booleanServer-side only if added then
mStorage
mixin don't executeselect
before execution ofupdate
. As a UNSAFE side effectupdate
won't check record is accessible to user. UNSAFE IfAudit
mixin is implemented for entity empty OldValue in inserted intouba_auditTrail
in case this flag is enabled, so better to think twice before skip select before update__skipRls
: booleanServer-side only
__skipAclRls
: booleanServer-side only
lockType
: stringFor entities with
softLock
mixin retrieve/set a lock during method execution Possible values:- 'None': get a lock info during select* execution (for a results with a single row)
Temp
orPersist
: set a lock (temp or persistent) together with select* execution (for a results with a single row)
// this server-side call will select all currency, including deleted
UB.Repository('cdn_currency').attrs(['ID'])
.misc({__allowSelectSafeDeleted: true}).selectAsArray();
# miscIf (addingCondition: *, flags: object) → CustomRepository instance
Helper method for CustomRepository.misc.
Calls misc
in case addingCondition is truthy
Arguments:
addingCondition
: *flags will be applied only in case addingCondition is truthy
flags
: object
# notExists (subRepository: CustomRepository, clauseNameopt: string) → CustomRepository instance
Adds where condition with NOT EXISTS
sub-query. See CustomRepository.exists for sample
Arguments:
subRepository
: CustomRepositoryRepository, what represent a sub-query to be execute inside EXISTS statement
clauseName
: stringOptional clause name
# orderBy (attr: string, directionopt: string) → CustomRepository instance
Sorting. If expression already exists in order list it direction will be changed or, in case direction === null it will be removed
Arguments:
let repo = UB.Repository('my_entity').attrs('ID').orderBy('code')
let orderedData = await repo.selectAsObject() // ordered. await is for client-side only
repo.orderBy('code', null) // remove order by code
let unorderedData = await repo.selectAsObject() // NOT ordered
# orderByDesc (attr: string) → CustomRepository instance
Adds descend sorting. The same as orderBy(attr, 'desc'). To remove such sorting call orderBy(attr, null)
Arguments:
attr
: string
UB.Repository('my_entity').attrs('ID')
// ORDER BY code, date_create DESC
.orderBy('code').orderByDesc('date_create')
# select (instanceopt: TubDataStore) → TubDataStore instance
Arguments:
instance
: TubDataStoreOptional instance for in-thread execution context. If passed - run select for it (not create new instance) and return instance as a result.
# selectAsArray (resultInPlainTextopt: Boolean) → TubCachedData | String instance
Return:
// todo this is TubCachedData structure!!!
Arguments:
resultInPlainText
= false: BooleanIf true - result is {String}
# selectAsArrayOfValues () → Array.<(string | number)> instance
For repository with ONE attribute returns a flat array of attribute values
const usersIDs = UB.Repository('uba_user'),attrs('ID').limit(100).selectAsArrayOfValues()
// usersIDs is array of IDs [1, 2, 3, 4]
# selectAsObject (fieldAliasesopt: Object.<string, string>, resultInPlainTextopt: boolean) → Array.<object> | string instance
# selectAsStore (instanceopt: TubDataStore) → TubDataStore | Array.<Object> instance
Create new, or use passed as parameter TubDataStore and run TubDataStore.select method passing result of CustomRepository.ubql() as config. Do not work for remote connection.
Arguments:
instance
: TubDataStoreOptional instance for in-thread execution context. If passed - run select for it (not create new instance) and return instance as a result. Be careful - method do not check instance is created for entity you pass to Repository constructor.
# selectById (ID: Number, fieldAliasesopt: Object.<string, string>) → Object | undefined instance
Select a single row by ID. If ubql result is empty - return {undefined}.
# selectScalar () → Number | String | undefined instance
Perform select and return a value of the first attribute from the first row
WARNING method do not check repository contains the single row
# selectSingle (fieldAliasesopt: Object.<string, string>) → Object | undefined instance
Select a single row. If ubql result is empty - return {undefined}.
WARNING method do not check repository contains the single row and always return a first row from result
# start (start: number) → CustomRepository instance
Retrieve first start
rows
Arguments:
start
: number
let store = UB.Repository('my_entity').attrs('ID')
//will return ID's from 15 to 25
.start(15).limit(10).select()
# ubql () → UBQL instance
Construct a UBQL JSON
let repo = UB.Repository('my_entity').attrs('ID').where('code', '=', 'a')
let inst = UB.DataStore(my_entity)
inst.run('select', repo.ubql())
# using (methodName: string) → CustomRepository instance
Retrieve a data from server using methodName
entity method.
By default, select
method will be used
Arguments:
methodName
: string
# where (expression: string, condition: CustomRepository.WhereCondition | string, valueopt: *, optionsopt: object) → CustomRepository instance
Adds where expression
-
the expression may contain one of the following functions: 'SUM', 'COUNT', 'AVG', 'MAX', 'MIN', 'CAST', 'COALESCE', 'LENGTH', 'LOWER', 'UPPER', 'DAY', 'MONTH', 'YEAR', 'ROUND', 'FLOOR', 'CEILING'
-
for a Date/DateTime attributes special macros
#maxdate
or#currentdate
can be used as a value:.where('dateValue', '=', '#maxdate') .where('dateTimeValue', '<', '#currentdate')
-
in
and 'notIn` conditions can take a sub-repository as a value parameter value. See CustomRepository.exists for sample -
for details how array parameters binds to DB query see array binding section in database tuning tutorial
Arguments:
expression
: stringAttribute name (with or without []) or valid expression with attributes in []
condition
: CustomRepository.WhereCondition| stringAny value from WhereCondition
value
: *Condition value. If
undefined
value not passed to ubqloptions
: object| stringclauseName
: stringclause name to be used in {CustomRepository.logicalPredicates}
- If not passed unique clause name will be generated ('_1', '_2', ..).
- In case a condition with the same name exists, it will be overwritten.
clearable
: booleanif === false then clearWhereList() will skip removing this where condition
If string is passed it means
clauseName
, otherwise an object {clauseName, clearable}
UB.Repository('my_entity').attrs('ID')
// code in ('1', '2', '3')
.where('code', 'in', ['1', '2', '3'])
// code in (select code from my_codes where id = 10)
.where('code', 'in', UB.Repository('my_codes').attrs('code').where('ID', '<', 10))
// name like '%homer%'
.where('[name]', 'contains', 'Homer')
//(birtday >= '2012-01-01') AND (birtday <= '2012-01-02')
.where('[birtday]', 'geq', new Date()).where('birtday', 'leq', new Date() + 10)
// (age + 10 >= 15)
.where('[age] -10', '>=', {age: 15}, 'byAge')
.where('LENGTH([code])', '<', 5)
// for condition match expression not need
.where('', 'match', 'myvalue')
# whereIf (addingCondition: *, expression: string, condition: CustomRepository.WhereCondition | string, valuesopt: *, clauseNameopt: string) → CustomRepository instance
Helper method for CustomRepository.where.
Calls where
in case addingCondition is truthy
Arguments:
addingCondition
: *Where expression will be added only in case addingCondition is truthy
expression
: stringAttribute name (with or without []) or valid expression with attributes in []
condition
: CustomRepository.WhereCondition| stringAny value from WhereCondition
values
: *Condition value. If
undefined
values not passed to ubqlclauseName
: stringOptional clause name to be used in {CustomRepository.logicalPredicates} If not passed where will generate unique clause named 'c1', 'c2', ......
let filterString = 'foundAllLikeThis' // or may be empty string
// with whereIf
let repo = UB.Repository('my_entity').attrs('ID').whereIf(filterString, 'myAttr', 'like', filterString)
//without whereIf
let repo = UB.Repository('my_entity').attrs('ID')
if (filterString) repo = repo.where('myAttr', 'like', filterString)
# withTotal (valueopt: boolean) → CustomRepository instance
Calculate total row number. WARNING!! This is VERY slow operation on DB level in case of many record
Result of calculation is returned in __totalRecCount parameter value in case selectAsArray()
client call:
Arguments:
value
= true: booleanIf
false
will remove total requirements
let result = UB.Repository('uba_user')
.attrs(['ID', 'description'])
.withTotal().selectAsArray();
console.log('Total count is:', result.__totalRecCount)
// Or into TubDataStore.totalRowCount in case of server side `selectAsStore()` call:
let store = UB.Repository('uba_user')
.attrs(['ID', 'description'])
.withTotal().selectAsStore();
console.log('Total count is:', store.totalRowCount);