Synopse

To content | To menu | To search

SQLite3 Framework

Entries feed

2012, Wednesday December 5

DataSnap-like Client-Server JSON RESTful Services in Delphi 6-XE3

Article update:
The server side call back signature changed since this article was first published in 2010. Please refer to the documentation or this forum article and associated commit.
The article was totally rewritten to reflect the enhancements.
And do not forget to see mORMot's interface-based services!

You certainly knows about the new DataSnap Client-Server features, based on JSON, introduced in Delphi 2010.
http://docwiki.embarcadero.com/RADStudi … plications

We added such communication in our mORmot Framework, in a KISS (i.e. simple) way: no expert, no new unit or new class. Just add a published method Server-side, then use easy functions about JSON or URL-parameters to get the request encoded and decoded as expected, on Client-side.

Continue reading...

2011, Sunday September 25

Synopse SQLite3 framework is now mORMot

In case you were redirected from the previous "Synopse SQLite3 framework" category link, here is the new thread to be used instead:
http://blog.synopse.info/category/Open-Source-Projects/mORMot-Framework

Since revision 1.15 of the framework, it is able to connect to any database engine (therefore is not limited to SQLite3), and is now called mORMot.

2011, Monday July 4

WinINet vs WinHTTP

If you want to implement an HTTP client access in your application, you may consider several choices:

  • Use the provided Indy components;
  • Use third-party components like Synapse, ICS or your own WinSock-based wrapper;
  • Use WinINet;
  • Use WinHTTP.

For our ORM, we tried to avoid external dependencies, and did not have the need of all Indy's features and overhead.
We fist wrote our own WinSock wrapper, then tried out WinInet.

When used on our testing benchmark, we found out that WinINet was dead slow.
Then we tried WinHTTP, the new API provided by Microsoft, and we found out this was blazing fast. As fast as direct WinSock access, without the need of writing all the wrapper code.

Continue reading...

2011, Sunday July 3

"Sharding" or "Share nothing" architecture

Here is what wikipedia states at http://en.wikipedia.org/wiki/Shared_nothing_architecture:

A shared nothing architecture (SN) is a distributed computing architecture in which each node is independent and self-sufficient, and there is no single point of contention across the system. People typically contrast SN with systems that keep a large amount of centrally-stored state information, whether in a database, an application server, or any other similar single point of contention.

This is just one approach of "sharding". Sharding is indeed related to a shared nothing architecture - once sharded, each shard can live in a totally separate logical schema instance.
"I sharded, therefore it scales"...

You can do this in Delphi... and opens a new world of scaling opportunities... Just as Google, Facebook, or eBay do... 

Continue reading...

2011, Wednesday June 29

Synopse SQLite3 framework 1.14

Our ORM framework has been released as version 1.14.

It's mainly a bug-fix release:

  • Integrated SQLite3 engine updated to latest version 3.7.7.1;
  • Fix several issues about JSON generation layout;
  • Enhanced automated User Interface generation for object on-screen edition;
  • SynPdf unit now handles Bézier curves from TCanvas, and some CMYK functions; also enhanced PDF/A-1compatibility;
  • Some speed enhancements, and new functions for the SynOleDB unit.

Continue reading...

2011, Sunday June 5

Synopse SQLite3 Framework 1.13

This is a major step for the framework.

Among a lot of new features and bug fixes:

Open Source project, for Delphi 6 up to XE, licensed under a MPL/LGPL/GPL tri-license.

Continue reading...

2011, Thursday June 2

Custom SQL functions

The SQLite3 engine defines some standard SQL functions, like abs() min() max() or upper().
A complete list is available at http://www.sqlite.org/lang_corefunc.html

One of the greatest SQLite3 feature is the ability to define custom SQL functions in high-level language. In fact, its C API allows to implement new functions which may be called within a SQL query. In other database engine, such functions are usually named UDF (for User Defined Functions).

Our framework allows you to add easily such custom functions, directly from Delphi classes.

Continue reading...

Fast JSON parsing

When it deals with parsing some (textual) content, two directions are usually envisaged. In the XML world, you have usually to make a choice between:
- A DOM parser, which creates an in-memory tree structure of objects mapping the XML nodes;
- A SAX parser, which reads the XML content, then call pre-defined events for each XML content element.

In fact, DOM parsers use internally a SAX parser to read the XML content. Therefore, with the overhead of object creation and their property initialization, DOM parsers are typically three to five times slower than SAX. But, DOM parsers are much more powerful for handling the data: as soon as it's mapped in native objects, code can access with no time to any given node, whereas a SAX-based access will have to read again the whole XML content.

Most JSON parser available in Delphi use a DOM-like approach. For instance, the DBXJSON unit included since Delphi 2010 or the SuperObject or DWS libraries create a class instance mapping each JSON node.

In a JSON-based Client-Server ORM like ours, profiling shows that a lot of time is spent in JSON parsing, on both Client and Server side. Therefore, we tried to optimize this part of the library.

Continue reading...

BATCH sequences for adding/updating/deleting records

When use the so-called BATCH sequences?

In a standard Client-Server architecture, especially with the common understanding (and most implementations) of a RESTful service, any Add / Update / Delete method call requires a back and forth flow to then from the remote server.

In case of a remote connection via the Internet (or a slow network), you could have some 100 ms of latency: it's just the "ping" timing, i.e. the time spent for your IP packet to go to the server, then back to you.

If you are making a number of such calls (e.g. add 1000 records), you'll have 100*1000 ms = 100 s = 1:40 min just because of this network latency!

The BATCH sequence allows you to regroup those statements into just ONE remote call. Internally, it builds a JSON stream, then post this stream at once to the server. Then the server answers at once, after having performed all the modifications.

Continue reading...

TSQLRecordRTree to implement R-Tree virtual tables

An R-Tree is a special index that is designed for doing range queries.

R-Trees are most commonly used in geospatial systems where each entry is a rectangle with minimum and maximum X and Y coordinates. Given a query rectangle, an R-Tree is able to quickly find all entries that are contained within the query rectangle or which overlap the query rectangle.

 This idea is easily extended to three dimensions for use in CAD systems. R-Trees also find use in time-domain range look-ups. For example, suppose a database records the starting and ending times for a large number of events. A R-Tree is able to quickly find all events, for example, that were active at any time during a given time interval, or all events that started during a particular time interval, or all events that both started and ended within a given time interval. And so forth. See http://www.sqlite.org/rtree.html

Since the 2010-06-25 source code repository update, the RTREE extension is compiled by default within all supplied .obj files of the framework.

A dedicated ORM class, named TSQLRecordRTree, is available to create such tables. It inherits from TSQLRecordVirtual, like the other virtual tables types (e.g. TSQLRecordFTS3 or our custom virtual tables).

Continue reading...

2011, Wednesday June 1

Business rules: validate and filter data

According to the n-Tier architecture, data filtering and validation should be implemented in the business logic, not in the User Interface.

If you were used to develop RAD database application using Delphi, you may have to change a bit your habits here. Data filtering and validation should be implemented not in the User Interface, but in pure Delphi code.

Data filtering is a process run on the User entry: for instance, it will trim left or right spaces, make the text uppercase...
Data validating is performed before saving the data to the database: for instance, an email address is checked for consistency, a field value to be unique...

Some try to implement this using an external scripting engine, in a procedure/event mode. Back to the 80th...
In our ORM framework, filtering and validation can be performed by creating some Delphi classes, which may be used on both Server and Client side.

Continue reading...

2011, Tuesday May 24

How to implement RESTful authentication

How to handle authentication in a RESTful Client-Server architecture is a matter of debate.

Commonly, it can be achieved, in the SOA over HTTP world via:
- HTTP basic auth over HTTPS;
- Cookies and session management;
- Query Authentication with additional signature parameters.

We'll have to adapt, or even better mix those techniques, to match our framework architecture at best.

Each authentication scheme has its own PROs and CONs, depending on the purpose of your security policy and software architecture.

Continue reading...

2011, Saturday May 14

Virtual Tables in the SQLite3 framework

The SQlite3 engine has ability to create Virtual Tables from code. From the perspective of an SQL statement, the virtual table object looks like any other table or view. But behind the scenes, queries from and updates to a virtual table invoke callback methods on the virtual table object instead of reading and writing to the database file.

The virtual table mechanism allows an application to publish interfaces that are accessible from SQL statements as if they were tables. SQL statements can in general do anything to a virtual table that they can do to a real table, with the following exceptions:
- One cannot create a trigger on a virtual table.
- One cannot create additional indices on a virtual table. (Virtual tables can have indices but that must be built into the virtual table implementation. Indices cannot be added separately using CREATE INDEX statements.)
- One cannot run ALTER TABLE ... ADD COLUMN commands against a virtual table.
- Particular virtual table implementations might impose additional constraints. For example, some virtual implementations might provide read-only tables. Or some virtual table implementations might allow INSERT or DELETE but not UPDATE. Or some virtual table implementations might limit the kinds of UPDATEs that can be made.

Example of virtual tables, already included in the SQLite3 engine, are FTS or RTREE tables. A custom virtual table might represent in-memory data structures (like TSQLVirtualTableJSON, TSQLVirtualTableBinary). Or it might represent a view of data on disk that is not in the SQLite3 format (e.g. TSQLVirtualTableLog). Or the application might compute the content of the virtual table on demand.

Thanks to the generic implementation of Virtual Table in SQLite3, you can use such tables in your SQL statement, and even safely execute a SELECT statement with JOIN or custom functions, mixing normal SQLite3 tables and any other Virtual Table.

A dedicated mechanism has been added to the framework, beginning with revision 1.13, in order to easily add such virtual tables with pure Delphi code, just by inheriting some classes.

Continue reading...

2011, Friday March 11

HTTP server using fast http.sys kernel-mode server

Since Windows XP SP2 and Windows Server 2003, the Operating System provides a kernel stack to handle HTTP requests. This http.sys driver is in fact a full featured HTTP server, running in kernel mode. It is part of the networking subsystem of the Windows operating system, as a core component.

The SynCrtSock unit can now implement a HTTP server based on this component. Of course, our SQLite3 framework will use it. If it's not available, it will launch our pure Delphi optimized HTTP server, using I/O completion ports and a Thread Pool.

Continue reading...

2011, Wednesday February 23

Fast JSON (un)serialization

The core of our SQLite3 framework is using JSON for all its Client/Server communication, and also for the internal cache of previous SQL requests.

There is indeed a damn fast JSON generator and parser in the framework. 

I've written some functions able to serialize and unserialize not only TSQLRecord (which is the main parent class of our ORM), but any TPersistent class instance.

Continue reading...

2011, Monday February 7

SQLite3 Framework updated to 1.12 - including engine 3.7.5

The Synopse SQLite3 Database Framework was just released under version 1.12:

  • internal SQLite3 database engine was updated to version 3.7.5, and SQL functions have been enhanced;
  • now handle prepared SQL statements with a neutral automated syntax;
  • with Delphi 2009/2010/XE, you can define directly Unicode string properties in TSQLRecord (will be stored as UTF-8);
  • include some overloaded methods using Variants for direct property access (e.g. in any grid);
  • SynPdf has now direct bookmarks and links methods, can reuse any existing bitmap, and generate PDF/A-1 files;
  • internal reporting now supports bookmarks and links (with on screen navigation), and better integrates with SynPdf;
  • a lot of bug fixes, new methods and enhancements.

Continue reading...

2010, Saturday December 18

SQL parameters can now be prepared "on the fly"

Up to now, most SQL statements were parsed, then prepared before execution.
Only individual TSQLRecord content retrieval was using prepared statements.

For the upcoming version 1.12 of the framework, we added an internal SQL statement cache in the database access.
That is, if a previous SQL statement is run with some parameters, a prepared version, available in cache, is used, and new parameters are bounded to it before the execution by SQLite3.

In some cases, it can speed the SQLite3 process a lot.

Continue reading...

2010, Monday December 13

SQLite3 Framework updated to 1.11 - including engine 3.7.4

The Synopse SQLite3 Database Framework was just released under version 1.11:

- internal SQLite3 database engine is updated to version 3.7.4;
- new TSQLRecordMany to handle "has many" and "has many through" relationships;
- new TSQLRecordFTS4 class, to handle the new FTS4 extension module;
- new RANK() function available in SQL statements for ranking FTS3/FTS4;
- introduces new TSQLite3DB, TSQLite3Statement, TSQLite3Blob, TSQLite3Value and TSQLite3FunctionContext types to clarify SQLite3 internal handle usage;
- new sqlite3_busy_timeout and sqlite3_busy_handler low-level functions, with new TSQLDataBase.BusyTimeout property;
- now handles User Defined Functions, via sqlite3_create_function_v2 and corresponding sqlite3_result_* functions;
- new MOD() and SOUNDEX() functions available in SQL statements;
- a lot of code refactoring, speed improvements, numerous fixes, new methods.

Continue reading...

2010, Thursday October 28

"has many" and "has many through" relationships

Extracted from wikipedia, here is a definition of 'many to many' relationships in regular database management:

In systems analysis, a many-to-many relationship is a type of cardinality that refers to the relationship between two entities (see also Entity-Relationship Model) A and B in which A may contain a parent row for which there are many children in B and vice versa. For instance, think of A as Authors, and B as Books. An Author can write several Books, and a Book can be written by several Authors. Because most database management systems only support one-to-many relationships, it is necessary to implement such relationships physically via a third and fourth junction table, say, AB with two one-to-many relationships A -> AB and B -> AB. In this case the logical primary key for AB is formed from the two foreign keys (i.e. copies of the primary keys of A and B).

In our SQLite3 framework, we just created a dedicated class for handling such "many to many" relationships.

Continue reading...

2010, Saturday October 23

Synopse SQLite3 Framework 1.10 - including engine 3.7.3

The Synopse SQLite3 Database Framework was just released under version 1.10:
- internal SQLite3 database engine is updated to version 3.7.3;
- code modifications to compile with Delphi 6 compiler;
- enhancements in TSQLRestServerStatic, for easier stand-alone work of this in-memory database engine;
- new SQLite3Edit unit, for automated creation of a UI window, ready to edit any TSQLRecord, with no RAD necessary (all components are created from RTTI): think this is an ORM for User Interface.

This version compiles from Delphi 6 up to Delphi XE.

Continue reading...

- page 1 of 2