Database interface
A JavaScript object implementing the Database
interface provides access to a relational style database.
See Database for documentation on how to use the relational database.
Construction
Database
objects cannot be directly created. See the database overview for how to use databases.
Use the db
property of your Plugin
.
Naming restrictions
Database table and field names must match this regular expression: \A[a-z][a-zA-Z0-9]*\z
Names must start with a lowercase letter, and be formed of letters and numbers only. Underscores are not allowed.
Interface
function table(name, fields, initialiserOrMethods)
Declares a table with the given name
and the defined fields
. See below for field definitions. There is an implicit numeric id
field in every table which is used as the primary key.
Note that by default, fields do not allow null
values, and you must specify nullable:true
to allow them. This is the other way round to SQL, where you need to specify NOT NULL
to disallow NULL
values.
A property is added to this object to access the new DatabaseTable
object.
The optional initialiserOrMethods
argument allows you to extend the prototype of the row object to add additional methods and getters and setters. If it’s a function, it’ll be called with the prototype as a single argument. If it’s a JavaScript Object
, those properties will be added to the prototype.
This function can only be called when the plugin is loaded. See the database overview for details and an example.
property T [access to tables]
A call of the table()
function to create a table with name T
, creates a property of this object with the name T
. The property exposes a DatabaseTable
object.
Field definitions
The fields
argument to table()
is a JavaScript Object
used as a dictionary of field name to field definition, another JavaScript Object
. The field definition object has the following keys:
key type
Name | Data type | JavaScript type |
text |
Unicode text 1 | String |
datetime |
Date and time, UTC timezone | Date |
date |
Date only | Date |
time |
Time only | DBTime |
boolean |
Boolean | true or false |
smallint |
16-bit signed integer | Number |
int |
32-bit signed integer | Number |
bigint |
64-bit signed integer 2 | Number |
float |
double precision floating point number | Number |
ref |
Reference to store object | Ref |
link |
Reference to row in other table | Database row object 3 |
user |
Reference to user | SecurityPrincipal 3 |
file |
File stored in the file store | File |
json |
JSON compatible data structure with automatic serialisation. | JavaScript Object see notes on json field limitations |
labelList |
Labels | LabelList |
key linkedTable
For link
types only. A string specifying the name of the table this refers to, if the name of the table does not match exactly the name of the field.
key nullable
If true
, null
values will be allowed for this field. Otherwise it’s an error to attempt to set the property to null
or save a new row object without specifying a value for this field.
key caseInsensitive
If true
for a text
field, any comparisons in queries will be case insensitive. The case of the string will be preserved in the database.
If an index is specified on a case insensitive field, the index will be case insensitive too, providing efficient indexed queries on the the field.
key indexed
If true
, an index will be created for this field.
key indexedWith
If set to an array of names of other fields, a multi-field index will be created with this field as the first field, then the others in order. Useful for speeding up queries on multiple fields, but use with caution.
key uniqueIndex
If true
and indexed
is set to true
or indexedWith
is specified, the resulting index will be a unique index. Attempting to store a row with duplicate value(s) will throw an exception.
Example table definition
P.db.table("employee", { firstName: { type:"text" }, lastName: { type:"text" }, user: { type:"user", nullable:true }, startDate: { type:"date" }, salary: { type:"int", nullable:true, indexed:true }, primaryExpertise: { type:"ref", indexed:true, uniqueIndex:true }, department: { type:"link", nullable:true, indexedWith:["startDate","salary"] } }, { name: function() { return this.firstName()+" "+this.lastName(); } });
JSON field type
json
fields automatically JSON serialise and deserialise values for convenience, but do come with limitations:
- Cannot be indexed
- Cannot be used in
where()
clauses, except when comparing tonull
- The deserialised value is mutable, so you have to think carefully about how you use the deserialised value
- So that errors in usage are easier to spot, you need to explicitly assign to the property to make a change which will be committed to the database when
save()
is called on the row.
// Where data is a json column... var row = P.db.table.create({data:{a:1,b:2}}); row.save(); var reloaded = P.db.table.load(row.id); reloaded.data.b = 3; // INCORRECT USAGE reloaded.save(); // Because line 5 mutated a cached value, it's not saved var reloaded2 = P.db.table.load(row.id); // reloaded2.data.b === 2 // To update the value, assign to the property reloaded2.data = {a:1,b:3}; // CORRECT reloaded2.save(); var reloaded3 = P.db.table.load(row.id); // reloaded3.data.b === 3
Notes
1 No maximum size is specified for text fields, because the underlying implementation is just as efficient for unrestricted text fields as it is for size limited text fields.
2 When using bigint
values, remember that JavaScript numbers can only represent 53-bit integers with full precision because it represents all numbers as a double precision floats.
3 link
and user
values can be set with numeric IDs, but properties in row objects always return the specified object.