#'
#' @importFrom methods new selectMethod setRefClass is
#' @import DBI
NULL
#' Class ModelDefinition (and methods)
#'
#' @description This class must be used to create the models
#' used by your programs.
#'
#'
#' @section Fields:
#' \describe{
#'
#' \item{\code{table}:}{Object of class \code{"character"}, the name of
#' the table. This field will be used to determine the name of the
#' resulting generated class}
#'
#' \item{\code{fields}:}{Object of class \code{"list"}, a named list.
#' The names are the fields of the table and the values are the SQL type
#' of the field (REAL, BOOLEAN, INTEGER, BLOB, or TEXT)}
#'
#' \item{\code{fk}:}{Object of class \code{"list"}, a simple list.
#' It contains the name of the tables that needs to be references by
#' this table.
#' Mutual references create linkage table.
#' One-way references create an fk field, named table_name_id.
#' }
#'
#' }
#' @export ModelDefinition
#' @exportClass ModelDefinition
#' @examples
#'
#' models <- list(
#' person=ModelDefinition(
#' table="person",
#' fields=list(
#' name="TEXT",
#' family_name="TEXT"
#' ), many=list("adress")
#' ## One person possibly has multiple adress. Or none...
#' ## "many" fields defines the creation of a linkage table
#' ## (many_to_many or one_to_many).
#' ## "one" fields defines a fk field enforced by a foreign key
#' ## restriction (one_to_one)
#' ## "many" fields mustn't be duplicated. So, "adress" must not
#' ## reference the "person" table.
#' ),
#' adress=ModelDefinition(
#' table="adress",
#' fields=list(
#' number="INTEGER",
#' street="TEXT"
#' )
#' )
#' )
ModelDefinition <- setRefClass(
"ModelDefinition",
fields=c(
table="character",
fields="list",
many="list",
one="list",
defaults="list"
)
)
#' Class ORM (and methods)
#'
#' ORM class is the main class of the orm package.
#' This is one of the only class that should be used by programmers
#'
#' @export ORM
#' @exportClass ORM
#'
#' @examples
#'
#' library(RSQLite)
#'
#' models <- list(
#' person=ModelDefinition(
#' table="person",
#' fields=list(
#' name="TEXT",
#' family_name="TEXT"
#' ), many=list("adress")
#' ## One person possibly has multiple adress. Or none...
#' ## "many" fields defines the creation of a linkage table
#' ## (many_to_many or one_to_many).
#' ## "one" fields defines a fk field enforced by a foreign key
#' ## restriction (one_to_one)
#' ## "many" fields mustn't be duplicated. So, "adress" must not
#' ## reference the "person" table.
#' ),
#' adress=ModelDefinition(
#' table="adress",
#' fields=list(
#' number="INTEGER",
#' street="TEXT"
#' )
#' )
#' )
#' DB_PATH <- "person.sqlite"
#' orm <- ORM(connection_params=list(DB_PATH), model_definitions=models)
#'
#' ## like this, we'll see the requests generated by the orm
#' print(orm$create_database())
#' ## the tables has been generated, fks and their restrictions has been
#' ## defined and linked table has been created if necessary
#'
#' ## we've created a person who's name is Alice Smith.
#' ## Alice has been saved into the database.
#' alice <- orm$person(name="Alice", family_name="smith")$save()
#'
#' ## Alice has been successfully added to and loaded from the database.
#' print(orm$person()$load_by(name="Alice"))
#'
#' ## The id is 1, because it's the first person to be inserted into the
#' ## "person" table.
#' ## The orm has generated an "INSERT" query.
#' print(alice$get_id())
#'
#' ## He's a boy, so he's changed his name to "Bob". Suits him better.
#' ## Fields must always be setted with "model$set_field_name(value)".
#' ## otherwise the orm will not see the modifications, and will not save
#' ## them in the database.
#' bob <- alice$set_name("bob")$save()
#'
#' ## still 1. Because the orm did not add new database entry.
#' ## The orm has generated an "UPDATE" query.
#' print(bob$get_id())
#'
#' ## prints an empty list()
#' ## no adress has been assigned to him for the moment.
#' print(bob$get_adress())
#'
#' ## let's give him a home
#' bob$add_adress(
#' ## the orm sanitizes the user's inputs and prevent sql injections.
#' orm$adress(number=42, street="Second street ; -- drop table person")
#' )
#' ## The orm detects that the adress object assigned to bob is not saved
#' ## yet in the database.
#' ## So, the orm will register the adress, and then create a link between
#' ## bob and the adress through a linkage table.
#' bob$save()
#'
#'
#' ## now Bob is happy because he has an adress
#' ## prints: list(<adress id: 1> ...) etc.
#' print(adress <- bob$get_adress())
#'
#' ## the street name is still somewat strange...
#' ## let's make it less strange
#' bob$get_adress(
#' ## we select the adress with a strange name...
#' street="Second street ; -- drop table person"
#'
#' ## we set a more... usual name. And we save it (the adress).
#' )[[1]]$set_street("Second street")$save()
#' print(bob$get_adress())
#'
#' ## never forget to disconnect when your're finished!
#' orm$disconnect()
#'
#' ## not to forget, there's a little trick:
#' ## this call orm$connect()
#' ## and at the end of the block, it calls orm$disconnect()
#' ## so you never foget to disconnect from the database.
#' orm <- ORM(connection_params=list(DB_PATH), model_definitions=models, connect=FALSE)
#' orm$with_connection({
#' bob <- orm$person()$load_by(name="bob")$first()
#' bob$add_adress(
#' ## he's has a second residence
#' orm$adress(number=2, street="the squirel's path")
#' )$save()
#' print(bob$get_adress())
#'
#' ## finily he decided to live in his second house, and sold the
#' ## first one.
#' print(bob$get_adress(street="Second street"))
#' bob$remove_adress(bob$get_adress(street="Second street")$first())
#' bob$save()
#' print(bob$get_adress())
#'
#' })
## now, you're disconnected from the database.
#' file.remove(DB_PATH)
#'
ORM <- setRefClass(
"ORM",
fields=c(
model_definitions_="list",
model_objects_="list",
in_memory="logical",
connected_="logical",
connection_parameters_="list",
connection_="DBIConnection",
# database_path="character",
request_pool="list",
execution_context="list",
sql="list",
DELETE_ALL_TABLES="character",
IF_NO_EXISTS="character",
CREATE_TABLE_TEMPLATE="character",
CREATE_LINKAGE_TABLE_TEMPLATE="character",
SELECT_WHERE_TEMPLATE="character",
DELETE_WHERE_TEMPLATE="character",
INSERT_WHERE_TEMPLATE="character",
UPDATE_WHERE_TEMPLATE="character",
FK_CONSTRAINT_TEMPLATE="character",
GROUP_BY_TEMPLATE="character",
OPERATORS="list",
LOGICAL_CONNECTORS="list",
escape_values__must_be_true__="logical",
dbms__="character",
SQLITE="character",
POSTGRESQL="character",
MARIADB="character",
MYSQL="character",
DBMS_PACKAGES="list",
DBMS_METHODS="list",
dbms_env="environment"
# is_connected="function",
# set_connection_parameters="function",
# connect="function",
# disconnect="function",
# clear_result="function",
# execute="function",
# send_query="function",
# get_query="function",
# send_statement="function",
# escape="function"
)
)
#' Class ModelMeta (and methods)
#'
#' @description This class is the super class of classes generated by
#' the model builder
#'
#'
ModelMeta <- setRefClass(
"ModelMeta",
fields=c(
modified__="list",
sql_model__="ModelDefinition",
table__="character",
orm__="ORM",
model_name__="character",
fields__="list",
loaded__="logical",
cache_read__="list",
cache_remove__="list",
cache_add__="list",
NOT_CREATED="numeric",
NOT_RETRIEVED="numeric",
id="numeric",
field_converters__="list",
defaults="list"
)
)
#' Class ResultSet (and methods)
#' @export ResultSet
#' @exportClass ResultSet
#'
#' @description This class contains a list of ModelMeta instances,
#' extracted from the database.
#'
#' @examples
#'
#' library(RSQLite)
#'
#' models <- list(
#' person=ModelDefinition(
#' table="person",
#' fields=list(
#' name="TEXT",
#' family_name="TEXT"
#' ), many=list("adress")
#' ## One person possibly has multiple adress. Or none...
#' ## "many" fields defines the creation of a linkage table
#' ## (many_to_many or one_to_many).
#' ## "one" fields defines a fk field enforced by a foreign key
#' ## restriction (one_to_one)
#' ## "many" fields mustn't be duplicated. So, "adress" must not
#' ## reference the "person" table.
#' ),
#' adress=ModelDefinition(
#' table="adress",
#' fields=list(
#' number="INTEGER",
#' street="TEXT"
#' )
#' )
#' )
#' DB_PATH <- "person.sqlite"
#' orm <- ORM(connection_params=list(in_memory=TRUE), model_definitions=models)
#'
#' ## like this, we'll see the requests generated by the orm
#' print(orm$create_database())
#' ## the tables has been generated, fks and their restrictions has been
#' ## defined and linked table has been created if necessary
#'
#' ## we've created a person who's name is Alice Smith.
#' ## Alice has been saved into the database.
#' orm$person(name="Alice", family_name="smith")$save()
#' print(orm$person()$load_by(name="Alice"))
ResultSet <- setRefClass(
"ResultSet",
fields=c(
result_set__="list",
length__="numeric",
df_built__="logical",
df_cache__="data.frame"
)
)
#' Class TableField (and methods)
#'
#' A class that defines a table's field. Translates to 'table'.'field'
#'
#' @export TableField
#' @exportClass TableField
#'
#' @examples
#'
#' library(RSQLite)
#' orm <- ORM(connection_params=list(in_memory=TRUE))
#' print(TableField(orm, "test", "field")$as.request)
TableField <- setRefClass(
"TableField",
fields=c(
table="character",
field="character"
)
)
#' Class OperatorClause (and methods)
#'
#' OperatorClause class defines a right and left TableFields and an
#' operator.
#' It translates to 'left'.'field' {{operator}} 'right'.'field'
#'
#' @export OperatorClause
#' @exportClass OperatorClause
#'
#' @examples
#'
#' library(RSQLite)
#' orm <- ORM(connection_params=list(in_memory=TRUE))
#' f1 <- TableField(orm, "test", "field")
#' f2 <- TableField(orm, "test2", "field2")
#' print(OperatorClause(
#' orm,
#' left=f1,
#' right=f2,
#' operator=orm$OPERATORS$GE
#' )$as.request)
OperatorClause <- setRefClass(
"OperatorClause",
fields=c(
left="TableField",
right="TableField",
operator="character"
)
)
#' Class JoinClause (and methods)
#'
#' JoinClause class defines a join clause between two tables.
#'
#' @export JoinClause
#' @exportClass JoinClause
#'
#' @examples
#'
#' library(RSQLite)
#' orm <- ORM(connection_params=list(in_memory=TRUE))
#' f1 <- TableField(orm, "test", "field")
#' f2 <- TableField(orm, "test2", "field2")
#' op <- OperatorClause(
#' orm,
#' left=f1,
#' right=f2,
#' operator=orm$OPERATORS$GE
#' )
#' print(JoinClause(orm, table="test", on=op))
JoinClause <- setRefClass(
"JoinClause",
fields=c(
table="character",
on="OperatorClause",
as="character",
kind="character"
)
)
#' Class WhereClause (and methods)
#'
#' WhereClause class defines a Where clause, that can encapsulate other
#' where clause(s)
#'
#' @export WhereClause
#' @exportClass WhereClause
#'
#' @examples
#'
#' library(RSQLite)
#' orm <- ORM(connection_params=list(in_memory=TRUE))
#'
#' print(WhereClause(
#' orm,
#' field=TableField(
#' orm,
#' table="linkage_table_name",
#' field=sprintf("%s_id", "table_1")
#' ),
#' operator=orm$OPERATORS$EQ,
#' value="id_1",
#' next_connector=orm$LOGICAL_CONNECTORS$AND,
#' next_clause=WhereClause(
#' orm,
#' field=TableField(
#' orm,
#' table="linkage_table_name",
#' field=sprintf("%s_id", "table_2")
#' ),
#' operator=orm$OPERATORS$EQ,
#' value="id_2"
#' )
#' ))
WhereClause <- setRefClass(
"WhereClause", fields=c(
field="TableField",
operator="character",
value="character",
next_connector="character",
next_clause="character"
)
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.