-
Notifications
You must be signed in to change notification settings - Fork 5
Working with data sources — ds
The primary component of Datasource is the ds
type, this is used to connect to and interact with data sources or used to define datasource connections. ds
types can be stored and worked with as locals or defined for convenient reuse.
When using ds
to connect to a data source there are a number of approaches you can take.
The most convenient way is with the below signature which leverages Lasso Admin and the configuration specified there:
ds(::database.table) or datasource(::database.table)
The first part of the tag specifies the database name and the second part the default table. These details are then used to lookup the host details using an optimised sqlite query. ::tags are used throughout Datasource due to the input restrictions they enforce (encouraging good naming conventions) and the clean distinct style they provide. That said, you can also use the below:
ds('database','table')
The fastest method to specify the data source is to do so directly and bypass Lasso admin:
ds(::mysqlds,'127.0.0.1',::database.table,'user','pass')
This is effectively one less database call (the host information search in Lasso Admin) and allows you to skip configuring your database in Lasso Admin completely. You don't need to specify a table, but when one is specified the table becomes the default table for the data source.
You can also use -named parameters:
ds(
-host = '127.0.0.1',
-database = 'database',
-table = 'table',
-username = 'username',
-password = 'password'
)
The full list of natively supported -params and defaults are:
-datasource::string='mysqlds'
-database::string=''
-table::string=''
-keycolumn::string='id'
-sql::string=''
-host::string=''
-port::integer=3306
-username::string=''
-password::string=''
-schema::string=''
-key::string=''
-encoding::string='UTF-8'
-maxrows::integer=50
As opposed to specifying the connection details for each call, it makes sense to define ds
connections for reuse. If a table is specified then this becomes the default table for the data source.
define store_ds => ds(::store.products)
This approach allows you to manage all of your connections within a single file independent of Lasso Admin and the current Lasso Instance. From then on you can reference the ds
anywhere in your code:
with row in store_ds->all->rows do {
// do something with each #row
}
You can also assign ds
to a local to work with:
local(store_ds) = ds(::store.products)
You can reference alternative tables via the ->table(::tag) method — it returns a reference to the ds
making all of the standard methods applicable to that table:
with row in store_ds->table(::users)->allrows do {
// do something with each user
}
You can also stack multiple ds
definitions (effectively leveraging other connection details):
define store_ds => ds(::store.products)
define product_ds => store_ds->table(::products)
define user_ds => store_ds->table(::users)
The above approach allows you to relocate databases and tables without having to update your working code. Your code will still refer to product_ds even after it's been moved to a different server, database or has been simply renamed. The above definitions would only be loaded once at startup (unless being redefined).
The default key column is id — you can also specify an alternative key columns:
ds(::store.products)->keycolumn(::guid)
ds(::store.products)->keycolumn('guid')
Or like this:
ds(
-database = 'store',
-table = 'products',
-keycolumn = 'guid'
)
By default the number of rows returned is 50, you can can specify the maximum number of rows on a connection level like so:
define product_ds => ds(::store.products)->maxrows(1000)
Or like this:
ds(
-database = 'store',
-table = 'products',
-maxrows = 1000
)
Alternatively the various search methods often allow for a maxrows parameter.
Datasource supports global settings, you can override them with the below definitions.
define ds_default_silent => false
define ds_default_maxrows => 50
The following methods invoke the data source and stores the results internally within Datasource. They also return a self reference allowing chainability and convenient querying of the ds
type.
####-> sql(statement::string,max::integer=50)::ds Execute the specified sql statement/s — if the string contains multiple SQL statements multiple result sets are stored. Multiple result sets can be accessed via the ->results method. By default ->rows returns the rows from the first result set.
with row in product_ds->sql(`
SELECT *
FROM products
WHERE brand = "example"
`)->rows do {
// do something with #row
}
Once working with rows you can also use Lasso's query syntax:
with row in product_ds->sql(...)->rows
where #row(::name) >> 'example' do {
// do something with #row
}
####-> search(...)::ds This allows for search input using classic inline parameters.
####-> all::ds, all(maxrows::integer) Finds all rows in the table (max rows defaults to all rows).
The following invoke the data source and return a static array containing the found rows.
####-> findrows(...)::staticarray This allows for search input using classic inline parameters using classic inline parameters.
with row in product_ds->findrows(
'brand' = 'example'
) do {
// do something with rows matching 'example'
}
####-> allrows(maxrows::integer)::staticarray Returns all rows from the table (max rows defaults to all rows).
with row in product_ds->allrows(100) do {
// do something with 100 rows
}
####-> where(equals::pair, ...), where(query::string, ...) Initialises the select_statement constructor — see the relevant portion of this document.
product_ds->where('brand' = 'example')
product_ds->where('brand LIKE "example"')
####-> select(column::tag,column::tag, ...), select(columns::trait_foreach) Also, initialises the select_statement constructor — see the relevant portion of this document.
product_ds->select(::id,::description)->where('brand' = 'example')
By default ds
assumes that the key column is id. This can be overridden by providing a pair to ->getrow or by specifying -keycolumn or ->keycolumn(::thecolumn)when defining the ds.
Return the first (and typically only) row matching the supplied key value:
-> getrow(keyvalue::integer)::ds_row or ::void
-> getrow(keyvalue::string)::ds_row or ::void
-> getrow(keyvalue::pair)::ds_row or ::void
// Get one row with an id of 3
local(row) = store_ds->getrow(3)
// Get one row where keycolumn uuid matchings
local(row) = store_ds->getrow(
'guid' = '8df6cff4-34f5-46b5-84d1-abe0e960cee0'
)
Return the first (and typically only) row matching the supplied key values:
-> getrow(keyvalue::integer,...)::ds_row or ::void
-> getrow(keyvalue::string,...)::ds_row or ::void
-> getrow(keyvalue::pair,...)::ds_row or ::void
// Get one row using multiple keycolumns
local(row) = store_ds->getrow(
'keya' = '8df6cff4-34f5'
'keyb' = 'abe0e960cee0'
)
You can retrieve multiple rows matching the supplied key values. A staticarray is returned containing any matched rows. If it is empty no rows were matched.
-> getrows(keyvalue::integer, ...)::staticarray
-> getrows(keyvalue::string, ...)::staticarray
-> getrows(keyvalues::trait_foreach)::staticarray
// Get rows with id of 1, 2 or 3
local(rows) = ds(::store.users)->getrows(1,2,3)
// Get rows with id of 1, 2 or 3
local(ids) = array(1,2,3,7,9)
local(rows) = ds(::store.users)->getrows(#ids)
The most straightforward way of modifying rows is either via rows themselves, with ds_row
, activerow
or an update_statement
— all of which are outlined later in this document. It is more productive to work directly with ds_row
and activerow
which leverage the below methods.
Update the specified row in the current table with the supplied data:
-> updaterow(data::map,key::integer)
-> updaterow(data::map,key::string)
-> updaterow(data::map,key::pair)
Update the specified row and table with the supplied data:
-> updaterow(intable::tag,data::map,key::integer)
-> updaterow(intable::tag,data::map,key::string)
-> updaterow(intable::tag,data::map,key::pair)
Add a row to the current table:
-> addrow(p::pair,p2::pair,...)
-> addrow(p::map)
#ds->addrow(
map(
'columnA' = 'this',
'colimnB' = 'that'
)
)
Add a row to the specified table:
-> addrow(totable::string,data::map)
-> addrow(totable::tag,data::map)
#ds->addrow(::toThisTable
map(
'columnA' = 'this',
'colimnB' = 'that'
)
)
#ds->addrow('toThisTable'
map(
'columnA' = 'this',
'colimnB' = 'that'
)
)
Delete the specified row from the current table:
-> deleterow(key::integer)
-> deleterow(key::string)
-> deleterow(key::pair, ...)
// Using an integer keyvalue (default key column id)
#ds->deleterow(1)
// Using a pair to specify an alternative key column
#ds->deleterow('uuid' = 'EE47590C-A1BA-4639-BAB8-EE8019E7D2DD')
Delete the specified row from the specified table:
-> deleterow(fromtable::tag,key::integer)
-> deleterow(fromtable::tag,key::string)
-> deleterow(fromtable::tag,key::pair)
// Using an integer keyvalue (default key column id)
#ds->deleterow('fromThisTable',1)
// Using a pair to specify an alternative key column
#ds->deleterow('fromThisTable','uuid' = 'EE47590C-A1BA-4639-BAB8-EE8019E7D2DD')