Live Demo
Demo DB Status
Remaining Demo Time
Maximum size
Current size
Available
Below, issue commands in real-time against your demo database.     more...
Modify and Query an Attribute
For our first example, we simply create a string attribute called "companyName" and assign it the value "ABC Incorporated". Then, within the same HTTP Request, we test our newly created attribute by running a query against it.

NOTE: It is not necessary to combine both the modify and query command within the same request (or another commands), but it does help simplify our examples by running both with a single click.

Try this
Try changing the "companyName" attribute from "ABC Incorporated" to something else.
Try using a function in your query (set sfql to "SELECT UPPER($s:companyName)")
Help
"modify"
The command used to add, edit and remove data.
"data"
The JSON named-value composed of an array of simple name-value pairs or even complete data graphs.
s: prefix
A SchemafreeSQL type-hint.
"s:companyName" tells SchemafreeSQL that the "companyName" attibute is of type "string".
"query"
The command to run a SFQL (Schema Free Query Language) query against your data.
"sfql"
Pass SFQL to the query command through this parameter.
$ prefix
Designate the beginning of an attribute name. For use within SFQL query statements.

Results:
Add Objects
SchemafreeSQL allows you to modify complete object graphs within a single "modify" command.

Each modify command can be run against any number of data elements (specified in the 'data' array).
And against each data element you can run one of 4 subcommands (add [the default], put, update or remove).
NOTE: each subcommand also accepts specific parameters, but we'll cover those later.

In this example, we use the default 'add' subcommand to create 2 phone objects.
Since 'add' is the default subcommand, we can either specify it explicitly (as in first phone object) or leave it off completely (as in the second phone object). Either way, the subcommand 'add' is executed.
NOTE: add always adds an additional object. If you click 'Execute' more than once, you will see what looks like the same phone objects being added to the database multiple times. But if you notice in our query, we also request the system attribute 'oid' of the phone objects which reveals that although we created multiple phone objects with exactly the same attribute names and values, they are in fact distinct objects, each able to be uniquely referenced by their intrinsic 'oid'.

Try this
Try changing the 'ORDER BY' to '$s:phone.value'.
Help
o: prefix
A SchemafreeSQL type-hint.
"o:phone" tells SchemafreeSQL that the "phone" attibute is of type "object".
"query"
The command to run a SFQL (Schema Free Query Language) query against your data.
"sfql"
Pass SFQL to the query command through this parameter.
$ prefix
Designate the beginning of an attribute name. For use within SFQL query statements.

Results:
Put Objects
You may have noticed on the previous example - which used the 'add' subcommand - that seemingly identical phone objects were created each time you clicked 'Execute'. However, if you look closely at the query results of that example - specifically the 'oid' attribute - you will notice that each phone object is in fact unique.

In practice, we probably would not want to add multiple 'mobile' or 'office' phone objects. Instead, we would want to add them only if they did not already exist and update them if they did exist. In this example, we will demonstrate how easy this is to do with SchemafreeSQL.

Most programmers are familiar with the programming concept of a indexed collection (e.g. a hashmap). If we were storing our example phone objects to such an indexed collection, we might key them by their 'name' (e.g. 'home' or 'office2') and use a 'put' command to store them to the collection.

In order to 'put' (instead of 'add') our phone objects into SchemafreeSQL, we simply use the 'put' subcommand along with the parameter 'match'.

Try this
Try changing the 'match' parameter to "$phone.oid=NNN" where NNN is equal to the oid of one of the phone objects as revealed in the query.
Try changing the 'value' attribute of a phone object.
Help
"put" subcommand
Add the object is no 'match' exists, otherwise update the matching object.
"match"
The parameter to the "put" subcommand which defines the SFQL query to use in matching the object. This parameter can include the full power of SFQL queries and as such is much more powerful than a simple indexed collection.

Results:
Multiple Queries in a Single Request
As we've already seen, multiple SchemafreeSQL commands can be executed per HTTP request (e.g. 'modify' & 'query').
In this example, we demonstrate how to differentiate between the results of multiple commands. Specifically, 'query' commands.

SchemafreeSQL provides a mechanism called reflective parameters. Reflective parameters are defined by you and are reflected back to you within the response. You define a reflective parameter by naming the parameter with a leading underscore "_".

Using reflective parameters, we simply create a parameter called "_queryId" and assign a unique value per query.

Try this
Try changing the reflective parameter '_queryId' to anything with a leading '_'
Try creating an additional reflective parameter. This will also be returned.
Help
_queryId
A user-defined reflective parameter.

Results:
Notice how your reflective parameters have been returned with their associated query results, enabling you to reference your query results by your chosen name and value.
Show Attributes
The command 'showAttributes' shows the current data structure at any level you like.

As the name 'SchemafreeSQL' implies, SchemafreeSQL enables you to store dynamic data structure at runtime, without having to set up schemas ahead of time. But when you want to examine the current state of your dynamic data structure, the simple-yet-powerful command 'showAttributes' will provide you with the information you need.

This example first inserts data, then issues various showAttributes commands.
Try this
Try changing the style to "nvp" (the default), "colnames", "dataonly" or "compact"
Help
oapath
the Object Attribute Path to restrict your listing to. For example, specifying 'employee.phone' will limit the listing to all attributes under not just the 'phone' objects but to the attributes under 'phone' objects which are under 'employee' objects. DEFAULT: no restriction to parent structure.
poid
the Parent OID. This is where the attribute listing will begin from in your hierarchy. 0 specifies the db root. Set to -1 or leave this parameter out to specify a parent-insensitve, global listing. DEFAULT: -1, no restriction to parend OID.
showCount
if set to 'true', a count of objects matching your specification will be included in the command output. DEFAULT: false
style
the return-style. "nvp":Name-Value Pairs, "colnames", "dataonly", or "compact". DEFAULT: nvp
recurse parameter
* COMING SOON - Recurse through child objects
depth parameter
* COMING SOON - Depth of recursion

Result Styles
Query result data can be returned in one of several styles. The style type is passed as a parameter to the query command.
  • dataonly (table format, data only)
  • colnames (table format, name of each table column in the top row)
  • nvp (Name-Value Pairs - the DEFAULT if no style is specified. Each data value is paired with it's name)
Try this
Try changing the "style" parameter from 'nvp' (the default, Name-Value Pairs) to 'colnames' or 'dataonly'.
Help
style parameter
The return-style. "nvp":Name-Value Pairs, "colnames", or "dataonly"

Results:
Linking Objects
What if we want we want to link to an existing object? For instance, if two people living in the same house share the same home address , then we would like to make a single instance of that address object and have each person linked to it.

To do this, we simply create the address object under one person, and link that address - using the 'put' subcommand - to the second person.
Notice that when globally searching (by specifying poid = -1), we also have to prefix the 'id' attribute with it's parent's attribute name ('address') as in '$i:address.id=11'. This is because a global search for the attribute 'id' alone would also hit 'id' attributes under 'person' objects as well. In this example, we want to restrict our 'id' match to 'address' objects only.

Help
poid parameter
The Parent ObjectID to search under. Use a value of -1 to indicate that you want to perform a 'global' search (i.e. a search across all instance of the given type, regardless of where they appear in your data structure)

Results:
Aggregate Queries
Of course you can also perform aggregate queries with SchemafreeSQL.

In this example we create some simple data items which resemble HTTP log entries. Hit execute multiple times to add more data and to see the difference in the query results.

Help
poid parameter
The Parent ObjectID to search under. Use a value of -1 to indicate that you want to perform a 'global' search (i.e. a search across all instance of the given type, regardless of where they appear in your data structure)

Results:
Dates and Time Zones
Export
Export produces a standard SFDB modify command containing the data of the current database. The resultant "modify" object in JSON is the equivalent to an import when run against the same or different SchemafreeSQL.
NOTE: If you use the mode 'put' instead of 'add', then data objects/attributes are updated instead of added. This makes it easy to create syncronization routines.
Try this
Try changing the "mode" parameter from 'add' to 'put'.

Results:
Timers
Use custom timers at any point in your request to measure the performance of your statements.
Available Commands: startTimer, stopTimer, pauseTimer, resumeTimer, getElapsedTimeMillis, getAccumulatedTimeMillis
Access your demo database from a remote host (e.g. your server).
SchemafreeSQL's interface is a simple HTTP Request/Response JSON format which can be easily implemented from any standard HTTP stack. Access to your Demo DB from a remote host will be enabled soon for your testing.

This will be made available as part of our beta program.
Please request an invite here.

Live Stats Example
Below is a live example using SchemafreeSQL to collect and report on various schemafreesql.com site statistics.

The data is being collected in real-time using http-bugs placed throughout this demo page and the aggregate analytics are being charted in real-time across all demo databases in use.

Event Types to plot

createdDemoDb
moreIntroTextOpen
ranDemo-Modify_And_Query_an_Attribute
ranDemo-Add_Objects
ranDemo-Put_Objects
ranDemo-Multiple_Queries_in_a_Single_Request
How we collect the data and store it to the database:
We created a simple javascript method to be placed behind certain onclick and other events.
And we designed it so that it could take advantage of SchemafreeSQL's dynamic data definition, thus allowing us to attach any name-value pair we liked to a recorded event.

sfa.a('s:eventId','createdDemoDb').send();

a() accepts a SchemafreeSQL type-hinted attribute name and a value and can be chained to additional a() calls to add additional attributes to the event being recorded.


The final call to send() sends the event to our server which issues the following call to the SchemafreeSQL service in order to record the event:
[{"modify": { "data":[
    {"o:events": [ {"add":{}},
        {"s:eventId": "createdDemoDb"},
        ... we set any other custom event attributes passed from js
            e.g. {"s:browser":"Firefox"}
        ... then we set some standard event properties 
            e.g. {"i:utcSeconds":"1337274032000"}, {"i:utcMinutes":"1337273160000"}, {"i:utcHours":"1337234400000"}
    ]}
]}}]

Of special note here is the fact that we did NOT have to go through any upfront steps of schema creation.
We simply started inserting our data.
The type-hinted prefixes used above are 'o'-object, 's'-string and 'i'-integer. See datatypes.


How we query the data from the database:
To query the hours graph, we issue the following query, substituting the min/max utcHours dependent upon the current time of day, and substituting the eventId types within the 'IN' statement with the list of eventIds we want to collect stats for.
[{"query":{
    "sfql": "SELECT $i:events.utcHours as 'd', $s:events.eventId as 'e', COUNT($events.oid) as 'c'  WHERE  $i:events.utcHours>=1337241600000 AND $i:events.utcHours<1337284800000 AND $s:events.eventId IN ('createdDemoDb','moreIntroTextOpen','ranDemo-Modify_And_Query_an_Attribute','ranDemo-Add_Objects') GROUP BY $i:events.utcHours, $s:events.eventId ORDER BY $i:events.utcHours"
}}]


To query the minutes graph, we issue the following query, substituting the min/max utcMinutes dependent upon the current time of day, and substituting the eventId types within the 'IN' statement with the list of eventIds we want to collect stats for.
[{"query":{
    "sfql": "SELECT $i:events.utcMinutes as 'd', $s:events.eventId as 'e', COUNT($events.oid) as 'c'  WHERE  $i:events.utcMinutes>=1337283780000 AND $i:events.utcMinutes<1337284680000 AND $s:events.eventId IN ('createdDemoDb','moreIntroTextOpen','ranDemo-Modify_And_Query_an_Attribute','ranDemo-Add_Objects') GROUP BY $i:events.utcMinutes, $s:events.eventId ORDER BY $i:events.utcMinutes"
}}]


To query the seconds graph, we issue the following query, substituting the min/max utcMinutes dependent upon the current time of day, and substituting the eventId types within the 'IN' statement with the list of eventIds we want to collect stats for.
[{"query":{
    "sfql": "SELECT $i:events.utcSeconds as 'd', $s:events.eventId as 'e', COUNT($events.oid) as 'c'  WHERE  $i:events.utcSeconds>=1337284608000 AND $i:events.utcSeconds<1337284628000 AND $s:events.eventId IN ('createdDemoDb','moreIntroTextOpen','ranDemo-Modify_And_Query_an_Attribute','ranDemo-Add_Objects') GROUP BY $i:events.utcSeconds, $s:events.eventId ORDER BY $i:events.utcSeconds"
}}]

Of special note here is the fact that we did NOT have to create any indexes in order for our queries to perform efficiently.
We simply query our data.