CustomRepository

CustomRepository

Ancestor for Browser/NodeJS ClientRepository and server side ServerRepository.

Do not use it directly, use UB.Repository on server side

Constructor

new CustomRepository(entityName)

Arguments:
  1. entityName (string)  name of Entity we create for

Members

WhereCondition: string

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')

Properties:
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
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(attr)CustomRepository

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'
Arguments:
  1. attr (string|Array.<string>)
Example
// 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', '=', 'Код1')
   .selectAsObject({'manyValue.caption': 'captions'})
 // result is `[{"ID":331947938939292,"manyValue":"1,2","captions":"caption 10,caption 20"}]`

 // Get attribute value for multilaguage ("isMultiLang": true in meta file) attribute other when current session language
 UB.Repository('org_employee').attrs(['ID', 'lastName_en^']).selectAsObject()

correlation(subQueryAttribute, masterAttribute, conditionopt, clauseNameopt)CustomRepository

If current repository is used as a sub-query for exists, notExists, in or notIn conditions correlation with a master repository will added
Arguments:
  1. subQueryAttribute (string)
  2. masterAttribute (string)
  3. [condition=eq] (WhereCondition|String)  A subset from WhereCondition list applicable for correlation join
  4. [clauseName] (string)  Optional clause name to be used in logic. If not passed unique clause names ('c1', 'c2', ...) where will be generated

exists(subRepository, clauseNameopt)CustomRepository

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:
  1. subRepository (CustomRepository)  Repository, what represent a sub-query to be execute inside EXISTS statement
  2. [clauseName] (string)  Optional clause name
Example
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 login 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)CustomRepository

Adds grouping
Arguments:
  1. attr (string|Array.<string>)  Grouped attribute(s)
Example
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)CustomRepository

Force where expressions to be used in join part of SQL statement instead of where part. Applicable only for not cached entities
Arguments:
  1. whereItemName (string)  name of where item to use in join.

joinCondition(expression, condition, valuesopt, clauseNameopt)CustomRepository

Adds join condition. Fix some known issues
Arguments:
  1. expression (string)  Attribute name (with or without []) or valid expression with attributes in [].
  2. condition (CustomRepository.WhereCondition)  Any value from WhereCondition list.
  3. [values] (*)  Condition value. In case expression is complex can take {Object} as value. In case values === undefined no values property passed to where list
  4. [clauseName] (string)  Optional clause name to be used in {CustomRepository.logicalPredicates}. If not passed where will generate unique clause named 'c1', 'c2', ......

limit(rowsLimit)CustomRepository

How many rows to select
Arguments:
  1. rowsLimit (number)
Example
// will return first two ID's from my_entity
let store = UB.Repository('my_entity').attrs('id').limit(2).selectAsObject()

logic(predicate)CustomRepository

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:
  1. predicate (string)  logical predicate.
Example
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')
 //(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')
 // (byCode OR byName) AND (all where items, not included in logic)
 .logic('(([byCode]) OR ([byName]))')

misc(flags)CustomRepository

Apply miscellaneous options to resulting UBQL
Arguments:
  1. flags (Object)
    Properties
    1. [__mip_ondate] (Date)  Specify date on which to select data for entities with dataHistory mixin. Default to Now()
    2. [__mip_recordhistory=false] (Boolean)  Select only record history data for specified ID (for entities with dataHistory mixin)
    3. [__mip_recordhistory_all=false] (Boolean)  Ignore __mip_ondate and select all data (acts as select for entities without dataHistory mixin)
    4. [__mip_disablecache=false] (Boolean)  For entities with cacheType in ["Session", "SessionEntity"] not check is data modified and always return result
    5. [__skipOptimisticLock=false] (Boolean)  Skip optimistic lock for entities with mStorage.simpleAudit = true
    6. [__allowSelectSafeDeleted=false] (Boolean)  Server-side only.
    7. [__skipSelectAfterUpdate=false] (Boolean)  Server-side only.
    8. [__skipSelectAfterInsert=false] (Boolean)  Server-side only.
    9. [__skipRls=false] (Boolean)  Server-side only.
    10. [__skipAclRls=false] (Boolean)  Server-side only.
Example
// this server-side call will select all currency, including deleted
  UB.Repository('cdn_currency').attrs(['ID'])
    .misc({__allowSelectSafeDeleted: true}).selectAsArray();

notExists(subRepository, clauseNameopt)CustomRepository

Adds where condition with NOT EXISTS sub-query. See CustomRepository.exists for sample
Arguments:
  1. subRepository (CustomRepository)  Repository, what represent a sub-query to be execute inside EXISTS statement
  2. [clauseName] (string)  Optional clause name

orderBy(attr, directionopt)CustomRepository

Sorting
Arguments:
  1. attr (string)  Sorted attribute
  2. [direction='asc'] (string)  Sort direction ('asc'|'desc')
Example
UB.CustomRepository('my_entity').attrs('ID').orderBy('code')

orderByDesc(attr)CustomRepository

Adds descend sorting. The same as orderBy(attr, 'desc')
Arguments:
  1. attr (string)
Example
UB.Repository('my_entity').attrs('ID')
  // ORDER BY code, date_create DESC
  .orderBy('code').orderByDesc('date_create')

select(storeConfigopt) abstract

Must be implemented in descendants as a alias to the most appropriate method
Arguments:
  1. [storeConfig]

selectAsArray() abstract

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": totolRecCountIfWithTotalRequest}

selectAsObject(fieldAliasesopt) → Array.<object> abstract

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"}]
Arguments:
  1. [fieldAliases] (Object.<string, string>)  Optional object to change attribute names during transform array to object

selectAsStore(storeConfigopt) abstract

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 adminUI client
  • array of array data representation for UnityBase remote connection
  • etc.
Arguments:
  1. [storeConfig]

selectById(ID)Object|undefined abstract

Select a single row by ID. If result is empty - returns undefined If result is not empty - returns a object
Arguments:
  1. ID (Number)  Row identifier
Example
UB.Repository('uba_user').attrs('name', 'ID').selectById(10).then(UB.logDebug)
  // will output: {name: "admin", ID: 10}

selectScalar()Number|String|undefined abstract

Execute select and returns a value of the first attribute from the first row
Example
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() → *|undefined abstract

Select a single row. If ubql result is empty - return undefined
Example
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)CustomRepository

Retrieve first start rows
Arguments:
  1. start (Number)
Example
let store = UB.Repository('my_entity').attrs('id')
 //will return ID's from 15 to 25
 .start(15).limit(10).select()

ubql()UBQL

Construct a UBQL JSON
Example
let repo = UB.Repository('my_entity').attrs('ID').where('code', '=', 'a')
let inst = UB.DataStore(my_entity)
inst.run('select', repo.ubql())

using(methodName)

Retrieve a data from server using methodName entity method. By default select method will be used.
Arguments:
  1. methodName (string)

where(expression, condition, valuesopt, clauseNameopt)CustomRepository

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 values parameter value. See CustomRepository#exists for sample

Arguments:
  1. expression (string)  Attribute name (with or without []) or valid expression with attributes in []
  2. condition (CustomRepository.WhereCondition|String)  Any value from WhereCondition
  3. [values] (*)  Condition value. If undefined values not passed to ubql
  4. [clauseName] (string)  Optional clause name to be used in {CustomRepository.logicalPredicates} If not passed where will generate unique clause named 'c1', 'c2', ......
Example
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').attr('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')

withTotal()CustomRepository

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:

    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);