Definition of SQL
SQL or Structured Query Language is an internatinal standard for manipulating data in a relational database.
Each Relational Database system like Oracle, MySQL or SQLite implements its own variation of the standard.
Fortunateley for the types of commands and queries that we will want to write, all of the implementations are much in agreement.
The relatively straightforward Select queries we will be writing to access data in our SQLite database will execute un-altered in many of the other environments.
Essentially you only have to learn SQL once.
SQL and Relational database tables
The strength of SQL is that a single SQL statement or query can request data be returned from one or many of the tables in the database.
You can essentially define the relationships between tables on-the-fly as part of your query statement.
DDL and DML
DDL
stands for Data Definition Language
.
- It is the set of SQL comands used to create alter of delete database objects such as tables.
DML
stands for Data Manipulation Language
. *Principally this is the SELECT
command which is used to extract data items from one or more of the database tables.
Simple SQL queries useing the Select statement
For the rest of this episode we will be looking at the SELECT statement.
To follow along, you should open the DB Browser application and connect to the SN7577
database.
The SELECT
statement
In SQL, querying data is performed by a SELECT
statement. A select statement has 6 key components;
library(DBI)
SELECT colnames
FROM tablename
GROUP BY colnames
WHERE conditions
HAVING conditions
ORDER BY colnames
- In practice very few queries will have all of these clauses in them simplifying many queries.
- On the other hand, conditions in the
WHERE
clause can be very complex and if you need to JOIN
two or more tables together then more clauses (JOIN and ON) are needed.
- All of the clause names above have been written in uppercase for clarity. SQL is not case sensitive.
- Neither do you need to write each clause on a new line, but it is often clearer to do so for all but the simplest of queries.
- In this episode we will start with the very simple and work our way up to the more complex.
- The simplest query is effectively one which returns the contents of the whole table
Select *
FROM SN7577;
- It is better practice and generally more efficient to explicitly list the column names that you want returned.
Select web1, web2, web3, web4
From SN7577;
- The
*
character acts as a wildcard meaning all of the columns but you cannot use it as a general wildcard. So for example, the following is not valid.
Select w*
From SN7577;
Select *
From SN7577
Limit 10;
Exercise
Write a query which returns the first 5 rows from the SN7577 table with only the columns Q1,Q2,Q3,Q4 and numage.
Solution:
Select Q1, Q2, Q3, Q4, numage
From SN7577
Limit 5;
The WHERE
Clause
- Usually you will want to restrict the rows returned based on some criteria. i.e. certain values or ranges within one or more columns.
- In this example we are only interested in rows where the value in the Q1 column is 2
Select Q1, Q3, Q4
From SN7577
Where Q1 = 2;
- In addition to using the
=
we can use many other operators such as <, <=, >, >=, <>
Using more complex logical expressions in the WHERE
clause
- We can also use the
AND
and OR
keywords to build more complex selection criteria.
Select Q1, Q3, Q4
From SN7577
Where Q1 > 5 and Q3 <> 2;
- You can ensure the precedence of the operators by using brackets.
- Note: Judicious use of brackets can also aid readability
Select Q1, Q3, Q4
From SN7577
Where Q1 = 5 or (Q3 <> 2 and Q4 > 8);
- The following query returns the rows where the value of Q1 either 5,6,7 or 8
Select Q1, Q3, Q4
From SN7577
Where Q1 > 5 and Q1 < 8;
- The same results could be obtained by using the
BETWEEN
or IN
operators
Select Q1, Q3, Q4
From SN7577
Where Q1 Between 5 and 8;
Select Q1, Q3, Q4
From SN7577
Where Q1 In (5, 6, 7, 8);
- The list of values in brackets do not have to be contiguous or even in order.
Exercise 1
In the SN7577
table the values of the web1, web2, web3, web4 columns are all -1, 0 or 1. The numage columns can be any value between 0 and 95.
Write a query which returns the web1, web2, web3, web4 and numage columns from the SN7577 table. The web1, web2, web3, web4 values should all be either 0 or 1 and the numage values should be between 30 and 40 inclusive. There are many ways of doing this, but try to use two different inequalities, an IN
clause and a BETWEEN
clause.
Solution:
select web1, web2, web3 , numage
from sn7577
where web1 >= 0 and web2 in (0, 1) and web3 <> -1 and numage between 30 and 40;
Sorting resutls
- If you want the results of your query to appear in a specific order, you can use the
ORDER BY
clause
Select Q1, Q3, Q4
From SN7577
Where Q1 In (5, 6, 7, 8)
Order By Q1;
- By default the SQL assumes Ascending order. You can make this more explicit by using the
ASC
or DESC
keywords.
Select Q1, Q3, Q4
From SN7577
Where Q1 In (5, 6, 7, 8)
Order By Q1 Desc;
- You can also order by multiple columns
Select Q1, Q3, Q4
From SN7577
Where Q1 In (5, 6, 7, 8)
Order By Q1 Desc, Q3 Asc;
Key points
Strictly speaking SQL is a standard, not a particular implementation
SQL implementation are sufficiently close that you only have to learn SQL once
The DDL constructs are used to create tables and other database objects
The DML constructs, typically the SELECT
statement is used to retrieve data from one or more tables
The SELECT
statement allows you to slice
and dice
the columns and rows of the dataset so that the query only returns the data of interest
LS0tCnRpdGxlOiAiVGhlIFNlbGVjdCBTdGF0ZW1lbnQiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgRGVmaW5pdGlvbiBvZiBTUUwKKiBTUUwgb3IgU3RydWN0dXJlZCBRdWVyeSBMYW5ndWFnZSBpcyBhbiBpbnRlcm5hdGluYWwgc3RhbmRhcmQgZm9yIG1hbmlwdWxhdGluZyBkYXRhIGluIGEgcmVsYXRpb25hbCBkYXRhYmFzZS4gCgoqIEVhY2ggUmVsYXRpb25hbCBEYXRhYmFzZSBzeXN0ZW0gbGlrZSBPcmFjbGUsIE15U1FMIG9yIFNRTGl0ZSBpbXBsZW1lbnRzIGl0cyBvd24gdmFyaWF0aW9uIG9mIHRoZSBzdGFuZGFyZC4KCiogRm9ydHVuYXRlbGV5IGZvciB0aGUgdHlwZXMgb2YgY29tbWFuZHMgYW5kIHF1ZXJpZXMgdGhhdCB3ZSB3aWxsIHdhbnQgdG8gd3JpdGUsIGFsbCBvZiB0aGUgaW1wbGVtZW50YXRpb25zIGFyZSBtdWNoIGluIGFncmVlbWVudC4gCgoqIFRoZSByZWxhdGl2ZWx5IHN0cmFpZ2h0Zm9yd2FyZCBTZWxlY3QgcXVlcmllcyB3ZSB3aWxsIGJlIHdyaXRpbmcgdG8gYWNjZXNzIGRhdGEgaW4gb3VyIFNRTGl0ZSBkYXRhYmFzZSB3aWxsIGV4ZWN1dGUgdW4tYWx0ZXJlZCBpbiBtYW55IG9mIHRoZSBvdGhlciBlbnZpcm9ubWVudHMuCgoqIEVzc2VudGlhbGx5IHlvdSBvbmx5IGhhdmUgdG8gbGVhcm4gU1FMIG9uY2UuCgojIFNRTCBhbmQgUmVsYXRpb25hbCBkYXRhYmFzZSB0YWJsZXMKKiBUaGUgc3RyZW5ndGggb2YgU1FMIGlzIHRoYXQgYSBzaW5nbGUgU1FMIHN0YXRlbWVudCBvciBxdWVyeSBjYW4gcmVxdWVzdCBkYXRhIGJlIHJldHVybmVkIGZyb20gb25lIG9yIG1hbnkgb2YgdGhlIHRhYmxlcyBpbiB0aGUgZGF0YWJhc2UuIAoKKiBZb3UgY2FuIGVzc2VudGlhbGx5IGRlZmluZSB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRhYmxlcyBvbi10aGUtZmx5IGFzIHBhcnQgb2YgeW91ciBxdWVyeSBzdGF0ZW1lbnQuCgojIERETCBhbmQgRE1MCiogYERETGAgc3RhbmRzIGZvciBgRGF0YSBEZWZpbml0aW9uIExhbmd1YWdlYC4gCiogSXQgaXMgdGhlIHNldCBvZiBTUUwgY29tYW5kcyB1c2VkIHRvIGNyZWF0ZSBhbHRlciBvZiBkZWxldGUgZGF0YWJhc2Ugb2JqZWN0cyBzdWNoIGFzIHRhYmxlcy4KKiBgRE1MYCBzdGFuZHMgZm9yIGBEYXRhIE1hbmlwdWxhdGlvbiBMYW5ndWFnZWAuIAoqUHJpbmNpcGFsbHkgdGhpcyBpcyB0aGUgYFNFTEVDVGAgY29tbWFuZCB3aGljaCBpcyB1c2VkIHRvIGV4dHJhY3QgZGF0YSBpdGVtcyBmcm9tIG9uZSBvciBtb3JlIG9mIHRoZSBkYXRhYmFzZSB0YWJsZXMuCgojIFNpbXBsZSBTUUwgcXVlcmllcyB1c2VpbmcgdGhlIFNlbGVjdCBzdGF0ZW1lbnQKKiBGb3IgdGhlIHJlc3Qgb2YgdGhpcyBlcGlzb2RlIHdlIHdpbGwgYmUgbG9va2luZyBhdCB0aGUgU0VMRUNUIHN0YXRlbWVudC4KCiogVG8gZm9sbG93IGFsb25nLCB5b3Ugc2hvdWxkIG9wZW4gdGhlIERCIEJyb3dzZXIgYXBwbGljYXRpb24gYW5kIGNvbm5lY3QgdG8gdGhlIGBTTjc1NzdgIGRhdGFiYXNlLgoKCiMgVGhlIGBTRUxFQ1RgIHN0YXRlbWVudAoKSW4gU1FMLCBxdWVyeWluZyBkYXRhIGlzIHBlcmZvcm1lZCBieSBhIGBTRUxFQ1RgIHN0YXRlbWVudC4gQSBzZWxlY3Qgc3RhdGVtZW50IGhhcyA2IGtleSBjb21wb25lbnRzOwoKYGBge3J9CmxpYnJhcnkoREJJKSAjbGlicmFyeSBhZGRlZCB0byBydW4gc3FsIGluIG5vdGVib29rCmBgYAoKCmBgYHNxbApTRUxFQ1QgY29sbmFtZXMKRlJPTSB0YWJsZW5hbWUKR1JPVVAgQlkgY29sbmFtZXMKV0hFUkUgY29uZGl0aW9ucwpIQVZJTkcgY29uZGl0aW9ucwpPUkRFUiBCWSBjb2xuYW1lcwpgYGAKCiogSW4gcHJhY3RpY2UgdmVyeSBmZXcgcXVlcmllcyB3aWxsIGhhdmUgYWxsIG9mIHRoZXNlIGNsYXVzZXMgaW4gdGhlbSBzaW1wbGlmeWluZyBtYW55IHF1ZXJpZXMuIAoqIE9uIHRoZSBvdGhlciBoYW5kLCBjb25kaXRpb25zIGluIHRoZSBgV0hFUkVgIGNsYXVzZSBjYW4gYmUgdmVyeSBjb21wbGV4IGFuZCBpZiB5b3UgbmVlZCB0byBgSk9JTmAgdHdvIG9yIG1vcmUgdGFibGVzIHRvZ2V0aGVyIHRoZW4gbW9yZSBjbGF1c2VzIChKT0lOIGFuZCBPTikgYXJlIG5lZWRlZC4KKiBBbGwgb2YgdGhlIGNsYXVzZSBuYW1lcyBhYm92ZSBoYXZlIGJlZW4gd3JpdHRlbiBpbiB1cHBlcmNhc2UgZm9yIGNsYXJpdHkuIApTUUwgaXMgbm90IGNhc2Ugc2Vuc2l0aXZlLiAKKiBOZWl0aGVyIGRvIHlvdSBuZWVkIHRvIHdyaXRlIGVhY2ggY2xhdXNlIG9uIGEgbmV3IGxpbmUsIGJ1dCBpdCBpcyBvZnRlbiBjbGVhcmVyIHRvIGRvIHNvIGZvciBhbGwgYnV0IHRoZSBzaW1wbGVzdCBvZiBxdWVyaWVzLgoqIEluIHRoaXMgZXBpc29kZSB3ZSB3aWxsIHN0YXJ0IHdpdGggdGhlIHZlcnkgc2ltcGxlIGFuZCB3b3JrIG91ciB3YXkgdXAgdG8gdGhlIG1vcmUgY29tcGxleC4KKiBUaGUgc2ltcGxlc3QgcXVlcnkgaXMgZWZmZWN0aXZlbHkgb25lIHdoaWNoIHJldHVybnMgdGhlIGNvbnRlbnRzIG9mIHRoZSB3aG9sZSB0YWJsZQoKYGBgc3FsClNlbGVjdCAqIApGUk9NIFNONzU3NzsKYGBgCiogSXQgaXMgYmV0dGVyIHByYWN0aWNlIGFuZCBnZW5lcmFsbHkgbW9yZSBlZmZpY2llbnQgdG8gZXhwbGljaXRseSBsaXN0IHRoZSBjb2x1bW4gbmFtZXMgdGhhdCB5b3Ugd2FudCByZXR1cm5lZC4KCmBgYHNxbApTZWxlY3Qgd2ViMSwgd2ViMiwgd2ViMywgd2ViNApGcm9tIFNONzU3NzsKYGBgCiogVGhlIGAqYCBjaGFyYWN0ZXIgYWN0cyBhcyBhIHdpbGRjYXJkIG1lYW5pbmcgYWxsIG9mIHRoZSBjb2x1bW5zIGJ1dCB5b3UgY2Fubm90IHVzZSBpdCBhcyBhIGdlbmVyYWwgd2lsZGNhcmQuIFNvIGZvciBleGFtcGxlLCB0aGUgZm9sbG93aW5nIGlzIG5vdCB2YWxpZC4KCmBgYHNxbApTZWxlY3QgdyoKRnJvbSBTTjc1Nzc7CmBgYAoKKiBJZiB5b3UgcnVuIGl0IHlvdSB3aWxsIGdldCBhbiBlcnJvci4gV2hlbiBhbiBlcnJvciBkb2VzIG9jY3VyIHlvdSB3aWxsIHNlZSBhbiBlcnJvciBtZXNzYWdlIGRpc3BsYXllZCBpbiB0aGUgYm90dG9tIHBhbmUuCgoqIEluIGFkZGl0aW9uIHRvIGxpbWl0aW5nIHRoZSBjb2x1bW5zIHJldHVybmVkIGJ5IGEgcXVlcnksIHlvdSBjYW4gYWxzbyBsaW1pdCB0aGUgcm93cyByZXR1cm5lZC4gCiogVGhlIHNpbXBsZXN0IGNhc2UgaXMgdG8gc2F5IGhvdyBtYW55IHJvd3MgYXJlIHdhbnRlZCB1c2luZyB0aGUgTGltaXQgY2xhdXNlLiAKKiBJbiB0aGlzIGV4YW1wbGUsIHRoZSBmaXJzdCB0ZW4gcm93cyBvZiB0aGUgcmVzdWx0IG9mIHRoZSBxdWVyeSB3aWxsIGJlIHJldHVybmVkLiAKKiBUaGlzIGlzIHVzZWZ1bCBpZiB5b3UganVzdCB3YW50IHRvIGdldCBhIGZlZWwgZm9yIHdoYXQgdGhlIGRhdGEgbG9va3MgbGlrZS4KCmBgYHNxbApTZWxlY3QgKgpGcm9tIFNONzU3NwpMaW1pdCAxMDsKYGBgCgojIyMgRXhlcmNpc2UKV3JpdGUgYSBxdWVyeSB3aGljaCByZXR1cm5zIHRoZSBmaXJzdCA1IHJvd3MgZnJvbSB0aGUgU043NTc3IHRhYmxlIHdpdGggb25seSB0aGUgY29sdW1ucyBRMSxRMixRMyxRNCBhbmQgbnVtYWdlLgoKU29sdXRpb246CmBgYHNxbAogU2VsZWN0IFExLCBRMiwgUTMsIFE0LCBudW1hZ2UKIEZyb20gU043NTc3CiBMaW1pdCA1OwpgYGAKCiMgVGhlIGBXSEVSRWAgQ2xhdXNlCgoqIFVzdWFsbHkgeW91IHdpbGwgd2FudCB0byByZXN0cmljdCB0aGUgcm93cyByZXR1cm5lZCBiYXNlZCBvbiBzb21lIGNyaXRlcmlhLiBpLmUuIGNlcnRhaW4gdmFsdWVzIG9yIHJhbmdlcyB3aXRoaW4gb25lIG9yIG1vcmUgY29sdW1ucy4KKiBJbiB0aGlzIGV4YW1wbGUgd2UgYXJlIG9ubHkgaW50ZXJlc3RlZCBpbiByb3dzIHdoZXJlIHRoZSB2YWx1ZSBpbiB0aGUgUTEgY29sdW1uIGlzIDIKCmBgYHNxbApTZWxlY3QgIFExLCAgUTMsIFE0CkZyb20gU043NTc3CldoZXJlIFExID0gMjsKYGBgCgoqIEluIGFkZGl0aW9uIHRvIHVzaW5nIHRoZSBgPWAgd2UgY2FuIHVzZSBtYW55IG90aGVyIG9wZXJhdG9ycyBzdWNoIGFzIGA8LCA8PSwgPiwgPj0sIDw+YAoKIyMjIFVzaW5nIG1vcmUgY29tcGxleCBsb2dpY2FsIGV4cHJlc3Npb25zIGluIHRoZSBgV0hFUkVgIGNsYXVzZQoKKiBXZSBjYW4gYWxzbyB1c2UgdGhlIGBBTkRgIGFuZCBgT1JgIGtleXdvcmRzIHRvIGJ1aWxkIG1vcmUgY29tcGxleCBzZWxlY3Rpb24gY3JpdGVyaWEuCgpgYGBzcWwKU2VsZWN0ICBRMSwgIFEzLCBRNApGcm9tIFNONzU3NwpXaGVyZSBRMSA+IDUgYW5kIFEzIDw+IDI7CmBgYAoKKiBZb3UgY2FuIGVuc3VyZSB0aGUgcHJlY2VkZW5jZSBvZiB0aGUgb3BlcmF0b3JzIGJ5IHVzaW5nIGJyYWNrZXRzLiAKKiBOb3RlOiBKdWRpY2lvdXMgdXNlIG9mIGJyYWNrZXRzIGNhbiBhbHNvIGFpZCByZWFkYWJpbGl0eQoKYGBgc3FsClNlbGVjdCAgUTEsICBRMywgUTQKRnJvbSBTTjc1NzcKV2hlcmUgUTEgPSA1IG9yIChRMyA8PiAyIGFuZCBRNCA+IDgpOwpgYGAKKiBUaGUgZm9sbG93aW5nIHF1ZXJ5IHJldHVybnMgdGhlIHJvd3Mgd2hlcmUgdGhlIHZhbHVlIG9mIFExIGVpdGhlciA1LDYsNyBvciA4CgpgYGBzcWwKU2VsZWN0ICBRMSwgIFEzLCBRNApGcm9tIFNONzU3NwpXaGVyZSBRMSA+IDUgYW5kIFExIDwgODsKYGBgCgoqIFRoZSBzYW1lIHJlc3VsdHMgY291bGQgYmUgb2J0YWluZWQgYnkgdXNpbmcgdGhlIGBCRVRXRUVOYCBvciBgSU5gIG9wZXJhdG9ycwpgYGBzcWwKU2VsZWN0ICBRMSwgIFEzLCBRNApGcm9tIFNONzU3NwpXaGVyZSBRMSBCZXR3ZWVuIDUgYW5kIDg7CmBgYAoqIHVzaW5nIGBJbmAKCmBgYHNxbApTZWxlY3QgIFExLCAgUTMsIFE0CkZyb20gU043NTc3CldoZXJlIFExIEluICg1LCA2LCA3LCA4KTsKYGBgCiogVGhlIGxpc3Qgb2YgdmFsdWVzIGluIGJyYWNrZXRzIGRvIG5vdCBoYXZlIHRvIGJlIGNvbnRpZ3VvdXMgb3IgZXZlbiBpbiBvcmRlci4KCiMjIEV4ZXJjaXNlIDEKSW4gdGhlIGBTTjc1NzdgIHRhYmxlIHRoZSB2YWx1ZXMgb2YgdGhlIHdlYjEsIHdlYjIsIHdlYjMsIHdlYjQgY29sdW1ucyBhcmUgYWxsIC0xLCAwIG9yIDEuIFRoZSBudW1hZ2UgY29sdW1ucyBjYW4gYmUgYW55IHZhbHVlIGJldHdlZW4gMCBhbmQgOTUuIAoKV3JpdGUgYSBxdWVyeSB3aGljaCByZXR1cm5zIHRoZSB3ZWIxLCB3ZWIyLCB3ZWIzLCB3ZWI0IGFuZCBudW1hZ2UgY29sdW1ucyBmcm9tIHRoZSBTTjc1NzcgdGFibGUuIFRoZSB3ZWIxLCB3ZWIyLCB3ZWIzLCB3ZWI0IHZhbHVlcyBzaG91bGQgYWxsIGJlIGVpdGhlciAwIG9yIDEgYW5kIHRoZSBudW1hZ2UgdmFsdWVzIHNob3VsZCBiZSBiZXR3ZWVuIDMwIGFuZCA0MCBpbmNsdXNpdmUuIFRoZXJlIGFyZSBtYW55IHdheXMgb2YgZG9pbmcgdGhpcywgYnV0IHRyeSB0byB1c2UgdHdvIGRpZmZlcmVudCBpbmVxdWFsaXRpZXMsIGFuIGBJTmAgY2xhdXNlIGFuZCBhIGBCRVRXRUVOYCBjbGF1c2UuCgojIyMgU29sdXRpb246CmBgYHNxbApzZWxlY3Qgd2ViMSwgd2ViMiwgd2ViMyAsICBudW1hZ2UKZnJvbSBzbjc1NzcKd2hlcmUgd2ViMSA+PSAwIGFuZCB3ZWIyIGluICgwLCAxKSBhbmQgd2ViMyA8PiAtMSBhbmQgbnVtYWdlIGJldHdlZW4gMzAgYW5kIDQwOwpgYGAKCiMgU29ydGluZyByZXN1dGxzCiogSWYgeW91IHdhbnQgdGhlIHJlc3VsdHMgb2YgeW91ciBxdWVyeSB0byBhcHBlYXIgaW4gYSBzcGVjaWZpYyBvcmRlciwgeW91IGNhbiB1c2UgdGhlIGBPUkRFUiBCWWAgY2xhdXNlCgpgYGBzcWwKU2VsZWN0IFExLCAgUTMsIFE0CkZyb20gU043NTc3CldoZXJlIFExIEluICg1LCA2LCA3LCA4KQpPcmRlciBCeSBRMTsKYGBgCiogQnkgZGVmYXVsdCB0aGUgU1FMIGFzc3VtZXMgQXNjZW5kaW5nIG9yZGVyLiBZb3UgY2FuIG1ha2UgdGhpcyBtb3JlIGV4cGxpY2l0IGJ5IHVzaW5nIHRoZSBgQVNDYCBvciBgREVTQ2Aga2V5d29yZHMuCgpgYGBzcWwKU2VsZWN0ICBRMSwgIFEzLCBRNApGcm9tIFNONzU3NwpXaGVyZSBRMSBJbiAoNSwgNiwgNywgOCkKT3JkZXIgQnkgUTEgRGVzYzsKYGBgCiogWW91IGNhbiBhbHNvIG9yZGVyIGJ5IG11bHRpcGxlIGNvbHVtbnMKCmBgYHNxbApTZWxlY3QgIFExLCAgUTMsIFE0CkZyb20gU043NTc3CldoZXJlIFExIEluICg1LCA2LCA3LCA4KQpPcmRlciBCeSBRMSBEZXNjLCBRMyBBc2M7CmBgYAoKIyMjIyMgS2V5IHBvaW50cwoqIFN0cmljdGx5IHNwZWFraW5nIFNRTCBpcyBhIHN0YW5kYXJkLCBub3QgYSBwYXJ0aWN1bGFyIGltcGxlbWVudGF0aW9uCgoqIFNRTCBpbXBsZW1lbnRhdGlvbiBhcmUgc3VmZmljaWVudGx5IGNsb3NlIHRoYXQgeW91IG9ubHkgaGF2ZSB0byBsZWFybiBTUUwgb25jZQoKKiBUaGUgRERMIGNvbnN0cnVjdHMgYXJlIHVzZWQgdG8gY3JlYXRlIHRhYmxlcyBhbmQgb3RoZXIgZGF0YWJhc2Ugb2JqZWN0cwoKKiBUaGUgRE1MIGNvbnN0cnVjdHMsIHR5cGljYWxseSB0aGUgYFNFTEVDVGAgc3RhdGVtZW50IGlzIHVzZWQgdG8gcmV0cmlldmUgZGF0YSBmcm9tIG9uZSBvciBtb3JlIHRhYmxlcwoKKiBUaGUgYFNFTEVDVGAgc3RhdGVtZW50IGFsbG93cyB5b3UgdG8gYHNsaWNlYCBhbmQgYGRpY2VgIHRoZSBjb2x1bW5zIGFuZCByb3dzIG9mIHRoZSBkYXRhc2V0IHNvIHRoYXQgdGhlIHF1ZXJ5IG9ubHkgcmV0dXJucyB0aGUgZGF0YSBvZiBpbnRlcmVzdAoKCgo=