New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DB API2 support in SmartHome.py used in SQLite plugin #69
Conversation
- always support sqlite3 - provide function sh.dbapi(<name>) to retrieve the given database API module
…dbapi-support Conflicts: bin/smarthome.py
# which is not part of DB API2 specification
- check DB API paramstyle and format SQL query accordingly # with generic statements we have a warning if we try to re-create # the table / index - there no common way to check if a table / index # exists # queries used will use the qmark style and will be converted accordingly
Trying to be more generic we also need to use generic/standard SQL queries. Some features are not available using standard SQL (e.g. The Further I start testing the |
database backends providing DB API 2 implementation
Added a new class
It can be used to execute simple queries, query for data and return one or all of them, make use of cursors explicitely by using |
- always register SQLite with "sqlite" alias since it is used with this alias in plugins already
Hi Oliver, I have to think about it... so long Marcus |
version numbers and the value is the query to update # the setup() method will create "version" table automatically to store the # current version of the database and upgrade accordingly when setup() is # called
I just commited a solution for:
The F.e. using the
... will automatically migrate the table structure and data to the new layout (don't know if all of the queries are working, it should only show what should be possible with this). The layout was changed to introduce a new ID column (in item and log table) and the data was migrated (based on the name in log table the ID in item table will be updated). |
…sing lock handle in close() function - add optional timeout parameter to lock() function
…other RDBMS - change index log_item_id to include time too # other RDBMS have the BIGINT type, which is simply mapped in SQLite to # INTEGER - but other RDBMS will handle it differently # and when including the time as the second field in index speeds up selections # which always will have a item and possibly a time
…the Database class for different plugins by using different names in constructor
# most other time columns are BIGINT, doing same here to keep consistency
…only create new cursor if no cursor was given
# represents the current status and the duration can not be calculated
- change "log" table to contain history entries and not the current status - put current status only into "item" table - fix duration calculation for "log" table - when stopping the plugin dump all current values into "log" and "item" table
…cted() in db module
. time should be id . add missing parameter cur
# sometimes it happens that the connection is closed by the server due to # idle time (mostly occurs when using multiple connections and one is # not under heavy use) - this way we verfiy the connection (and reconnect # if required) before fetching data
… be logged to database or not # usually you want to store item changes into the database and want to read them # later - in some cases, especially when generating data from external systems, # it would be useful to just be able to read the values from the database, but also # read and update the item value / current status without modifying the underlying # database records
- make use of insertItem() in id() method and add flag if new items should be created automatically - fix ACL check in update_item() method
. try to find out the max time value lower then start time . include found max time value as start time . additionally restrict selection including duration
…no log data is logged currently to database with timestamp lower then starting point # using COALESCE() SQL function seems to be suiteable, since it returns the # first non-NULL value and this function is supported by several database # servers (e.g. MySQL, Oracle, PostgreSQL, SQLite)
…e of an exception
… there is no such data for then end range # this is already done for start timestamp, now also for end timestamp
# the indexes are now unique
# usually a transaction is created and needs an explicit commit (see code # above) and in case of error make sure the rollback is done
- use existing cursor object in _dump() when calling id() method
# check introduced in commit 9f4e2b8
…ove the items which are currently dumped while keeping the rest # concurrent access to the buffer may added some items in the meantime
…estamp instead of keeping the timestamps in a local list
# make use of DB-API possible in early setup
Created new PR smarthomeNG/smarthome#131 in new project and will close this issue now. Thanks for your great application! |
This pull request implements three things:
dblog
which logs item changes to a database and use different implementation (currently only tested with SQLite, but should also work with any MySQL DB API2 implementation)I implemented this in one pull request, since the
dblog
plugin depends on the DB API enhancement. The documentation is also updated and can be provided in a new pull request when this is merged.Using database backends
I thought about how to use different database implementation / backends with SmartHome.py and came to this implementation.
It adds a new configuration setting to
smarthome.conf
calleddb
. This configures the database backend implementation (need to implement the DB API 2 specifications to have a common interface available) and defaults tosqlite:sqlite3
, which means the SQLite API is available using the aliassqlite
and the Python modulesqlite3
.Since SQLite is bundled with Python directly you do not need to explicitely configure this - it's always added as default if not registered explicitely. It's also possible to register multiple database backends using
|
, e.g.db = sqlite:sqlite3 | mysql:mysqldb
.Additionally to this configuration the SmartHome.py core have a new function called
dbapi(alias)
which returns the module for the given alias (e.g. in the case abovesh.dbapi('sqlite')
will return thesqlite3
module and you can do something like this:For convenience a new class
lib.db.Database
was added which can be constructed by using the following codeThe first identifier argument is just a name which is used when something is written to the log and one want to identifier which database connection is related to a log message. Additionally to this, it is also used internally (e.g. to name the
version
table) - so just us characters like[a-zA-Z0-9_]
and do not start with numbers.The second DB API parameter is the module of the database backend implementation. In this example it will use the SQLite backend implementation which is registered as default.
The third connect parameter is a
dict
containing all connection parameters required to invoke the module'sconnect()
function. Alternatively this can also be a simple string using a map-like syntax of parameters, e.g.host:localhost | port:1234 | ...
- see also below.Use DB API in SQLite plugin
This pull request will make use of this new feature in the SQLite plugin already to be able to use other database backends later (not part of this pull request and may be implemented in a new pull request and maybe a new plugin which could obsolete the SQLite plugin; suggestions are welcome!).
Since the SQLite module already implements the DB API2 specification it was not really hard to change it. The plugin implementation was already using the specification and the patch is very simple (just use the
sh.dbapi('sqlite')
- everything else seems to be working well.The 'sqlite' backend is always automatically registered and available.
New Plugin
dblog
The new plugin is logging item changes to the database. It was tested using a SQLite database to log changes to. It will not do any pack mechanism which is the SQLite plugin doing. It's something like a log and stores all changes to the database.
The amount of data could be large when SmartHome.py is running long time. That's why it also support other database backends (e.g. MySQL or PostgreSQL).
The configuration of this plugin is simple:
sqlite
- which is registered as default)connect()
function (e.g. for SQLite something likeconnect = database:/path/to/log.db | check_same_thread:0
) - the parameters depends on the database implementationThis plugin is already using the new
lib.db.Database
class to do something with the database backend.