Ancestor for Browser/Node.js ClientRepository and server side ServerRepository.
Do not use it directly, use UB.Repository on a server side or UB.Repository / UB.LocalRepository on client side
# new CustomRepository (entityName: string)
Arguments:
entityName: stringname of Entity we create for
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'
- for PostGIS
ST_*(Topological Relationships, Distance Relationships, Measurement Functions) are allowed. Restriction - first argument must be bracket attribute, oll other - either parameters or numeric constant
// 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()
// PostGIS
UB.Repository('tstgeo_geometry').attrs('ID', 'ST_Area([geoLine])')
.where('ST_Intersects([geo], ?)', 'custom', '{"type":"LineString","coordinates":[[0,0],[0,2]]}')
.select()
# 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
dataHistorymixin. Default to Now()__mip_recordhistory: booleanSelect only record history data for specified ID (for entities with
dataHistorymixin)__mip_recordhistory_all: booleanIgnore __mip_ondate and select all data (acts as select for entities without
dataHistorymixin)__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
mStoragemixin don't executeselectbefore execution ofupdate. As a UNSAFE side effectupdatewon't check record is accessible to user. UNSAFE IfAuditmixin is implemented for entity empty OldValue in inserted intouba_auditTrailin 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
softLockmixin retrieve/set a lock during method execution Possible values:- 'None': get a lock info during select* execution (for a results with a single row)
TemporPersist: 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 (storeConfigopt: object) instance
Must be implemented in descendants as a alias to the most appropriate method
Arguments:
storeConfig: objectoptional config passed to store constructor
# selectAsArray () instance
Must be implemented in descendants and return (or resolved for async clients)
to array of array representation of result, like this
{"resultData":{"fields":["ID","name","ID.name"],"rowCount":1,"data":[[10,"admin","admin"]]},"total":1,"__totalRecCount": totalRecCountIfWithTotalRequest}
# selectAsArrayOfValues () → Array.<(string | number)> instance
For repository with ONE attribute returns a flat array of attribute values
// get first 100 all ID's of tst_dictionary entity
UB.Repository('tst_dictionary').attrs('ID').limit(100).selectAsArrayOfValues()
// returns array of IDs: [1, 2, 3, 4]
# selectAsObject (fieldAliasesopt: Object.<string, string>) → Array.<object> instance
Must be implemented in descendants and return (or resolved for async clients)
to array of object representation of result, like this
[{"ID":3000000000004,"code":"uba_user"},{"ID":3000000000039,"code":"uba_auditTrail"}]
# selectAsStore (storeConfigopt: object) instance
Must be implemented in descendants and return (or resolved for async clients)
to DataSet class instance, implemented in caller level. It can be:
- {TubDataStore} for in-server context
- {UB.ux.data.UBStore} for UnityBase
adminUIclient array of arraydata representation for UnityBase remote connection- etc.
Arguments:
storeConfig: objectoptional config passed to store constructor
# selectById (ID: number, fieldAliasesopt: Object.<string, string>) → object | undefined instance
Select a single row by ID. If result is empty - returns undefined
If result is not empty - returns object
Arguments:
ID: numberRow identifier
fieldAliases: Object.<string, string>Optional object to change attribute names during transform array to object. See selectAsObject
UB.Repository('uba_user').attrs('name', 'ID').selectById(10).then(UB.logDebug)
// will output: {name: "admin", ID: 10}
# selectScalar () → number | string | undefined instance
Execute select and returns a value of the first attribute from the first row
UB.Repository('uba_user')
.attrs('name')
.where('ID', '=', 10)
.selectScalar().then(UB.logDebug) // will output `admin`
**WARNING** does not check if result contains the single row
# selectSingle (fieldAliasesopt: Object.<string, string>) → * | undefined instance
Select a single row. If ubql result is empty - return undefined
Arguments:
fieldAliases: Object.<string, string>Optional object to change attribute names during transform array to object. See selectAsObject
UB.Repository('uba_user').attrs('name', 'ID').where('ID', '=', 10)
.selectSingle().then(UB.logDebug)
// will output: {name: "admin", ID: 10}
**WARNING** method does not check if result contains the single row and always returns 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 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 PostGIS
ST_*(Topological Relationships, Distance Relationships, Measurement Functions) are allowed. Restriction - first argument must be bracket attribute, oll other - either parameters or numeric constant -
for a Date/DateTime attributes special macros
#maxdateor#currentdatecan be used as a value:.where('dateValue', '=', '#maxdate') .where('dateTimeValue', '<', '#currentdate') -
inand '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
undefinedvalue 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
undefinedvalues 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
falsewill 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);
