Objectives

About table joins

SELECT Q1,
       count(*) as how_many
FROM SN7577
GROUP BY Q1;
image
image

INNER JOIN

  1. In the select clause you can make it clear from which table each of the selected columns comes from by prefixing the column name with the table alias followed by a period. You could use the full table name but by selecting short, single letter alias’ you can save a lot of typing.

  2. The column names that you wish to join on may have the same name and so you need some way of distinguishing between them.

Using simple alias’ for the tables our join SQL looks like this:

SELECT q.value,
       count(*) as how_many
FROM SN7577 s
JOIN Question1  q
ON q.key = s.Q1
GROUP BY  s.Q1
image
image

Exercise

SELECT q.value,
       count(*) as how_many
FROM SN7577 s
JOIN Question1  q
ON q.key = s.Q1
GROUP BY  s.Q1
  1. Change the SQL so that the group by clause is the value column from the Question1 table. Run the query. How are the results different?

  2. Can you change the SQL so that table alias’ are not used? Does this aid readability or not?

Solution:

  1. You only have to substitute q.value for s.Q1 in the GROUP BY clause. Essentially the same results are returned but now they are in alphabetical order of the Quustion1 value column text.
  • Because there are no conflicts in the column names between the two tables you could write the query without using alias’ for the tables. Including the alias’ adds clarity and readability to the SQL, especially if you are selecting several columns from each of the tables.

Different join types

The example of a join given above is called an INNER join, ** we could have written INNER JOIN rathere than simply **JOIN. * This is almost never done in practice as the inner join is by far the most common join type used.

There are severeal different join types possible

image
image

In SQLite only the Inner join, the Left Outer join and the Cross join are supported. * You can create a Right outer join by swapping the tables in the From and Join clauses. * A Full outer join is the combination of the Left outer and Right outer joins.

Using different join types in analysing your data

image * These tables have been included in the SN7577 database

image image image

Exercise

  1. Modify the first Left Outer Join query above so that only the joined rows where there is no match in the Animals_Eat table are returned.
SELECT a.*, e.*
FROM Animals as a
LEFT OUTER JOIN Animals_Eat as e
on a.ID_A = e.ID_E
  1. Modify the second Left Outer Join query above so that only the the Id_E column from the Animals_Eat table is returned where there is no matching row in the Animal table.
SELECT a.*, e.*
FROM Animals_Eat as a
LEFT OUTER JOIN Animals as a
on a.ID_A = e.ID_E

####Solution:

SELECT a.* , e.*
FROM Animals  as a
Left outer Join  Animals_Eat as e
on  a.Id_A = e.Id_E
where e.Id_e is NULL;
SELECT Id_E
FROM Animals_Eat
Left outer Join Animals
ON  Id_A = Id_E
WHERE Id_A is NULL
ORDER by Id_E;

Because there is no conflict in the column names across the two tables, we have chosen not to use alias’. Notice that the Id_A column which we are checking for NULL doesn’t have to be a returned column.

key points

  • Joins are used to combine data from two or more tables.

  • Tables to be joined must have a column in each which represent the same thing

  • There are several different types of joins

  • The Inner join is the most commonly use

  • You may have to use the other join types to discover missing data or gaps in your data

LS0tCnRpdGxlOiAiVGFibGUgSm9pbnMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KIyMjIyBPYmplY3RpdmVzCiogVW5kZXJzdGFuZCB0aGUgc3RydWN0dXJlIG9mIGEgam9pbmVkIHRhYmxlCiogRmFtaWxpYXJpdHkgd2l0aCB0aGUgZGlmZmVyZW50IGpvaW4gdHlwZXMKKiBVc2UgZGlmZmVyZW50IGpvaW4gdHlwZXMgaW4gYW5hbHlzaW5nIHlvdXIgZGF0YQoqIFVuZGVyc3RhbmQgd2hhdCBvdGhlciBqb2luIHR5cGVzIGNhbiB0ZWxsIHlvdSBhYm91dCB5b3VyIGRhdGEKCiMjIEFib3V0IHRhYmxlIGpvaW5zCiogSW4gYW55IHJlbGF0aW9uYWwgZGF0YWJhc2Ugc3lzdGVtLCB0aGUgYWJpbGl0eSB0byBqb2luIHRhYmxlcyB0b2dldGhlciBpcyBhIGtleSBxdWVyeWluZyByZXF1aXJlbWVudC4gCgoqIGBKb2luc2AgYXJlIHVzZWQgdG8gY29tYmluZSB0aGUgcm93cyBmcm9tIHR3byAob3IgbW9yZSkgdGFibGVzIHRvZ2V0aGVyIHRvIGZvcm0gYSBzaW5nbGUgdGFibGUuIAoqIEEgam9pbiBiZXR3ZWVuIHRhYmxlcyB3aWxsIG9ubHkgYmUgcG9zc2libGUgaWYgdGhleSBoYXZlIGF0IGxlYXN0IGBvbmUgY29sdW1uIGluIGNvbW1vbmAuIAoKKiBUaGUgY29sdW1uIGRvZXNu4oCZdCBoYXZlIHRvIGhhdmUgdGhlIHNhbWUgbmFtZSBpbiBlYWNoIHRhYmxlLCBhbmQgcXVpdGUgb2Z0ZW4gdGhleSB3b27igJl0LCBidXQgdGhleSBkbyBoYXZlIHRvIGhhdmUgYSBjb21tb24gdXNhZ2UuCgoqIEZvciBleGFtcGxlIHRoZSBRdWVzdGlvbjEgdGFibGUgaGFzIGJlZW4gY3JlYXRlZCBmcm9tIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBRMSBpbiB0aGUgU043NTc3IGRhdGEgZGljdGlvbmFyeSBmaWxlLiAKCiogVGhlcmUgYXJlIG9ubHkgdHdvIGNvbHVtbnMgVGhlIHZhbHVlIGNvbHVtbiBpbmRpY2F0ZXMgYSByZXNwb25kZW50cyB2b3RpbmcgaW50ZW50aW9ucyBhbmQgdGhlIGtleSBjb2x1bW4gaGFzIHRoZSB2YWx1ZSB3aGljaCBpcyB1c2VkIHRvIHJlcHJlc2VudCB0aGlzIGludGVudGlvbiBpbiB0aGUgU043NTc3IHRhYmxlLgoqIFlvdSBjYW4gc2VlIGltbWVkaWF0ZWx5IGZyb20gdGhpcyB0aGF0IHRoZXJlIGlzIGEgY29ubmVjdGlvbiBvciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdGhlIHR3byB0YWJsZXMuIAoqIFRoZSBrZXkgY29sdW1uIGluIHRoZSBRdWVzdGlvbjEgdGFibGUgaGFzIGJlZW4gZGVmaW5lZCBhcyBhIHByaW1hcnkga2V5LiAKKiBUaGlzIGd1YXJhbnRlZXMgdGhhdCB0aGUga2V5IGNvbHVtbiBoYXMgYSB1bmlxdWUgc2V0IG9mIHZhbHVlcy4gCiogQWx0aG91Z2ggbm90IHJlcXVpcmVkLCBpdCBpcyBnZW5lcmFsbHkgdGhlIGNhc2UgdGhhdCB0aGUgdmFsdWVzIGluIG9uZSBvZiB0aGUgY29sdW1ucyB0aGF0IHRoZSB0YWJsZXMgaGF2ZSBpbiBjb21tb24gd2lsbCBoYXZlIHVuaXF1ZSB2YWx1ZXMgaW4gaXQuIAoqIEl0IGlzIGFsc28gbm90IHJlcXVpcmVkIGJ1dCBnZW5lcmFsbHkgdGhlIGNhc2UgdGhhdCB0aGUgdW5pcXVlIGNvbHVtbiB3aWxsIGJlIGEgcHJpbWFyeSBrZXkgaW4gb25lIG9mIHRoZSB0YWJsZXMuCgoqIEluIHRoZSBgU043NTc3YCB0YWJsZSwgdGhlIHZhbHVlcyBpbiB0aGUgYFExIGNvbHVtbmAgYXJlIHRoZSBga2V5IHZhbHVlc2AgaW4gdGhlIGBRMSB0YWJsZWAuIAoqIFlvdSB3b3VsZCBub3QgZXhwZWN0IHRoZXNlIHRvIGJlIHVuaXF1ZSwgbWFueSByZXNwb25kZW50cyBtYXkgaGF2ZSB0aGUgc2FtZSB2b3RpbmcgaW50ZW50aW9ucy4KCiogSWYgd2Ugd2FudGVkIHRvIGZpbmQgb3V0IHRoZSB2b3RpbmcgaW50ZW50aW9ucyBvZiBhbGwgb2YgdGhlIHJlc3BvbmRlbnRzIHdlIGNvdWxkIHdyaXRlIGEgc2ltcGxlIGFnZ3JlZ2F0aW9uIHF1ZXJ5IGxpa2UgdGhpczoKCmBgYHNxbApTRUxFQ1QgUTEsCiAgICAgICBjb3VudCgqKSBhcyBob3dfbWFueQpGUk9NIFNONzU3NwpHUk9VUCBCWSBRMTsKYGBgCiFbaW1hZ2VdKGltYWdlcy9qb2luczEucG5nKQoKIyMgSU5ORVIgSk9JTgoKKiBXaGF0IHdlIHdvdWxkIHJlYWxseSBsaWtlIHdvdWxkIGJlIHRvIGhhdmUgdGhlIHRleHQgdmFsdWVzIG9mIHRoZSB2b3RpbmcgaW50ZW50aW9ucyB0byBtYWtlIHRoZSByZXN1bHRzIG1vcmUgcmVhZGFibGUuCgoqIFdlIGNhbiBhY2hpZXZlIHRoaXMgYnkgam9pbmluZyB0aGUgUXVlc3Rpb24xIHRhYmxlIHdpdGggdGhlIFNONzU3NyB0YWJsZS4KCiogVGFibGUgbmFtZXMgbGlrZSBjb2x1bW4gbmFtZXMgY2FuIGJlIGdpdmVuIGFuIGFsaWFzLiAKKiBUaGlzIGlzIGFsbW9zdCBhbHdheXMgZG9uZSB3aGVuIGpvaW5pbmcgdGFibGVzLiAKKiBUaGVyZSBhcmUgdHdvIHJlYXNvbnMgZm9yIGRvaW5nIHRoaXMuCgoxLiBJbiB0aGUgc2VsZWN0IGNsYXVzZSB5b3UgY2FuIG1ha2UgaXQgY2xlYXIgZnJvbSB3aGljaCB0YWJsZSBlYWNoIG9mIHRoZSBzZWxlY3RlZCBjb2x1bW5zIGNvbWVzIGZyb20gYnkgcHJlZml4aW5nIHRoZSBjb2x1bW4gbmFtZSB3aXRoIHRoZSB0YWJsZSBhbGlhcyBmb2xsb3dlZCBieSBhIHBlcmlvZC4gWW91IGNvdWxkIHVzZSB0aGUgZnVsbCB0YWJsZSBuYW1lIGJ1dCBieSBzZWxlY3Rpbmcgc2hvcnQsIHNpbmdsZSBsZXR0ZXIgYWxpYXPigJkgeW91IGNhbiBzYXZlIGEgbG90IG9mIHR5cGluZy4KCjIuIFRoZSBjb2x1bW4gbmFtZXMgdGhhdCB5b3Ugd2lzaCB0byBqb2luIG9uIG1heSBoYXZlIHRoZSBzYW1lIG5hbWUgYW5kIHNvIHlvdSBuZWVkIHNvbWUgd2F5IG9mIGRpc3Rpbmd1aXNoaW5nIGJldHdlZW4gdGhlbS4KClVzaW5nIHNpbXBsZSBhbGlhc+KAmSBmb3IgdGhlIHRhYmxlcyBvdXIgam9pbiBTUUwgbG9va3MgbGlrZSB0aGlzOgoKYGBgc3FsClNFTEVDVCBxLnZhbHVlLAogICAgICAgY291bnQoKikgYXMgaG93X21hbnkKRlJPTSBTTjc1NzcgcwpKT0lOIFF1ZXN0aW9uMSAgcQpPTiBxLmtleSA9IHMuUTEKR1JPVVAgQlkgIHMuUTEKCmBgYAoqIEhlcmUgd2UgaGF2ZSBzZWxlY3RlZCB0aGUgYHZhbHVlYCBjb2x1bW4gZnJvbSB0aGUgYFF1ZXN0aW9uMSB0YWJsZWAgYXMgdGhpcyBoYXMgdGhlIHRleHQgdmFsdWUgdGhhdCB3ZSB3YW50LiAKKiBUaGUgYWdncmVnYXRpb24gcmVtYWlucyB0aGUgc2FtZS4gCiogVGhlIGBKT0lOIGNsYXVzZWAgbmFtZXMgdGhlIHNlY29uZCB0YWJsZSBhbmQgdGhlIGBPTiBjbGF1c2VgIGdpdmVzIHRoZSBjcml0ZXJpYSBieSB3aGljaCB0aGUgdGFibGVzIGFyZSB0byBiZSBqb2luZWQuIAoqIFRoZSByZXN1bHRzIG9idGFpbmVkIGFyZToKCiFbaW1hZ2VdKGltYWdlcy9qb2luczIucG5nKQoKCiogVGhlIHJlc3VsdHMgYXJlIHRoZSBzYW1lIGFzIGJlZm9yZSBleGNlcHQgdGhhdCB0aGUgdGhlIHRleHQgb2YgdGhlIHZhbHVlIGNvbHVtbiBmcm9tIHRoZSBRdWVzdGlvbnMxIHRhYmxlIGhhcyByZXBsYWNlZCB0aGUgbnVtZXJpYyB2YWx1ZSBmcm9tIHRoZSBRMSBjb2x1bW4gaW4gdGhlIFNONzU3NyB0YWJsZS4KCiogTm90aWNlIHRoYXQgdGhlIHRoZSBgR1JPVVAgQllgIGNvbHVtbiBkb2VzIG5vdCBhcHBlYXIgaW4gdGhlIGBTRUxFQ1QgY2xhdXNlYC4KCgojIyBFeGVyY2lzZQoKYGBgc3FsClNFTEVDVCBxLnZhbHVlLAogICAgICAgY291bnQoKikgYXMgaG93X21hbnkKRlJPTSBTTjc1NzcgcwpKT0lOIFF1ZXN0aW9uMSAgcQpPTiBxLmtleSA9IHMuUTEKR1JPVVAgQlkgIHMuUTEKCmBgYAoKMS4gQ2hhbmdlIHRoZSBTUUwgc28gdGhhdCB0aGUgZ3JvdXAgYnkgY2xhdXNlIGlzIHRoZSB2YWx1ZSBjb2x1bW4gZnJvbSB0aGUgUXVlc3Rpb24xIHRhYmxlLiBSdW4gdGhlIHF1ZXJ5LiBIb3cgYXJlIHRoZSByZXN1bHRzIGRpZmZlcmVudD8KCjIuIENhbiB5b3UgY2hhbmdlIHRoZSBTUUwgc28gdGhhdCB0YWJsZSBhbGlhc+KAmSBhcmUgbm90IHVzZWQ/IERvZXMgdGhpcyBhaWQgcmVhZGFiaWxpdHkgb3Igbm90PwoKCiMjIyBTb2x1dGlvbjoKMS4gWW91IG9ubHkgaGF2ZSB0byBzdWJzdGl0dXRlIHEudmFsdWUgZm9yIGBzLlExYCBpbiB0aGUgYEdST1VQIEJZYCBjbGF1c2UuIEVzc2VudGlhbGx5IHRoZSBzYW1lIHJlc3VsdHMgYXJlIHJldHVybmVkIGJ1dCBub3cgdGhleSBhcmUgaW4gYWxwaGFiZXRpY2FsIG9yZGVyIG9mIHRoZSBRdXVzdGlvbjEgdmFsdWUgY29sdW1uIHRleHQuCgoqIEJlY2F1c2UgdGhlcmUgYXJlIG5vIGNvbmZsaWN0cyBpbiB0aGUgY29sdW1uIG5hbWVzIGJldHdlZW4gdGhlIHR3byB0YWJsZXMgeW91IGNvdWxkIHdyaXRlIHRoZSBxdWVyeSB3aXRob3V0IHVzaW5nIGFsaWFz4oCZIGZvciB0aGUgdGFibGVzLiBJbmNsdWRpbmcgdGhlIGFsaWFz4oCZIGFkZHMgY2xhcml0eSBhbmQgcmVhZGFiaWxpdHkgdG8gdGhlIFNRTCwgZXNwZWNpYWxseSBpZiB5b3UgYXJlIHNlbGVjdGluZyBzZXZlcmFsIGNvbHVtbnMgZnJvbSBlYWNoIG9mIHRoZSB0YWJsZXMuCgoKIyMgRGlmZmVyZW50IGpvaW4gdHlwZXMKClRoZSBleGFtcGxlIG9mIGEgam9pbiBnaXZlbiBhYm92ZSBpcyBjYWxsZWQgYW4gYElOTkVSIGpvaW5gLCAqKiB3ZSBjb3VsZCBoYXZlIHdyaXR0ZW4gKipJTk5FUiBKT0lOICoqIHJhdGhlcmUgdGhhbiBzaW1wbHkgKipKT0lOLiAKKiBUaGlzIGlzIGFsbW9zdCBuZXZlciBkb25lIGluIHByYWN0aWNlIGFzIHRoZSBpbm5lciBqb2luIGlzIGJ5IGZhciB0aGUgbW9zdCBjb21tb24gam9pbiB0eXBlIHVzZWQuCgoqIE90aGVyIEpvaW4gdHlwZXMgYXJlIGF2YWlsYWJsZeKApgoKKiBCZWZvcmUgd2UgbG9vayBhdCB0aGUgb3RoZXIgYGpvaW4gdHlwZWBzIHdlIG5lZWQgdG8gZXhwbGFpbiBob3cgdGhlIGBJbm5lciBqb2luYCB3b3JrcyBhbmQgd2h5IGl0IGlzIHNvIGNvbW1vbmx5IHVzZWQuCgoqIFRvIGlsbHVzdHJhdGUgdGhpcyBmb3IgYWxsIGpvaW5zIHdlIGFyZSBkZWZpbmluZyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byB0YWJsZXMgYmFzZWQgb24gdGhlIGRhdGEgdmFsdWVzIGluIHR3byBjb2x1bW5zLCBvbmUgZnJvbSBlYWNoIHRhYmxlLiAKCiogV2hhdCB0aGF0IHJlbGF0aW9uc2hpcCBpcywgaXMgZ2l2ZW4gYnkgdGhlIGNyaXRlcmlhIGluIHRoZSBgT04gY2xhdXNlYC4gCiogVGhlIHZhbHVlIG9mIHRoZSBjb2x1bW4gaW4gb25lIHRhYmxlIG11c3QgYmUgc2FtZSBhcyB0aGF0IGluIHRoZSBvdGhlciB0YWJsZS4KCiogVGhlIHRhYmxlIHNwZWNpZmllZCBpbiB0aGUgYEZST00gY2xhdXNlYCBpcyB1c2FsbHkgdGhlIHRhYmxlIHdpdGggdGhlIGB1bmlxdWUga2V5c2AgYW5kIHdlIHdhbnQgdG8gam9pbiBpdCB3aXRoIHRoZSB0YWJsZSBpbiB0aGUgYEpPSU4gY2xhdXNlYCB3aGljaCBoYXMgYSBjb2x1bW4gd2hpY2ggY29udGFpbiB0aGUga2V5IHZhbHVlcywgYnV0IGFyZW7igJl0IG5lY2Vzc2FyaWx5IHVuaXF1ZS4gCiogUXVpdGUgb2Z0ZW4gdGhleSBhcmUgbm90IGV4cGVjdGVkIHRvIGJlIHVuaXF1ZS4gVGhleSBhcmUgZXhwZWN0ZWQgdG8gZXhpc3QgdGhvdWdoLgoKKiBXaGVuIGEgcmVsYXRpb25hbCBkYXRhYmFzZSBpcyBkZWZpbmVkIGFuZCB0aGUgdGFibGVzIHNldCB1cCBpbml0aWFsbHkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0YWJsZXMgYXJlIGFscmVhZHkga25vd24sIHRoZXkgYXJlIHBhcnQgb2YgdGhlIGRlc2lnbiBvZiB0aGUgb3ZlcmFsbCBkYXRhYmFzZS4KCiogQmVjYXVzZSBvZiB0aGlzIGl0IGlzIHBvc3NpYmxlIHRvIGVuc3VyZSB3aGVuIHRoZSBkYXRhIGlzIGFkZGVkIHRvIHRoZSB0YWJsZXMgdGhhdCB0aGVyZSB3aWxsIGJlIGVudHJpZXMgaW4gYm90aCB0YWJsZXMgd2hpY2ggaGF2ZSBtYXRjaGluZyB2YWx1ZXMuIAoqIEF0IHRoZSB2ZXJ5IGxlYXN0IHlvdSBjYW4gcHJldmVudCByb3dzIGJlaW5nIGFkZGVkIHRvIHRoZSBzZWNvbmQgdGFibGUgd2l0aCBhIHZhbHVlIGluIHRoZSBjb2x1bW4geW91IGludGVuZCB0byBqb2luIG9uIGZvciB3aGljaCB0aGVyZSBpcyBubyBtYXRjaGluZyBjb2x1bW4gaW4gdGhlIGZpcnN0IHRhYmxlLgoKKiBBbiBgaW5uZXIgam9pbmAgb25seSByZXR1cm5zIHJvd3Mgd2hlcmUgdGhlcmUgaXMgYSBgbWF0Y2hgIGJldHdlZW4gdGhlIHR3byBjb2x1bW5zLiAKKiBJbiBtb3N0IGNhc2VzIHRoaXMgd2lsbCBiZSBhbGwgb2YgdGhlIGNvbHVtbnMgc2VsZWN0ZWQgZnJvbSB0aGUgZmlyc3QgdGFibGUgYW5kIDAsMSBvciBtb3JlIGNvbHVtbnMgc2VsZWN0ZWQgZnJvbSB0aGUgc2Vjb25kIHRhYmxlLgoKKiBUaGUgcmVsYXRpb25hbCBkZXNpZ24gbWFrZXMgdXNlIG9mIG11bHRpcGxlIHRhYmxlcyBhcyBhIHdheSBvZiBhdm9pZGluZyByZXBldGl0aW9uIG9mIGRhdGEuIAoqICoqSm9pbmluZyB0YWJsZXMgcmUtaW50cm9kdWNlcyB0aGUgcmVwbGljYXRpb24gb2YgdGhlIGRhdGEqKgoKIyMgVGhlcmUgYXJlIHNldmVyZWFsIGRpZmZlcmVudCBqb2luIHR5cGVzIHBvc3NpYmxlCgohW2ltYWdlXShpbWFnZXMvam9pbnR5cGVzLnBuZykKCkluIFNRTGl0ZSBvbmx5IHRoZSBgSW5uZXIgam9pbmAsIHRoZSBgTGVmdCBPdXRlciBqb2luYCBhbmQgdGhlIGBDcm9zcyBqb2luYCBhcmUgc3VwcG9ydGVkLiAKKiBZb3UgY2FuIGNyZWF0ZSBhIGBSaWdodCBvdXRlciBqb2luYCBieSBzd2FwcGluZyB0aGUgdGFibGVzIGluIHRoZSBgRnJvbWAgYW5kIGBKb2luYCBjbGF1c2VzLiAKKiBBIGBGdWxsIG91dGVyIGpvaW5gIGlzIHRoZSBjb21iaW5hdGlvbiBvZiB0aGUgYExlZnQgb3V0ZXIgYW5kIFJpZ2h0IG91dGVyIGpvaW5zYC4KCiMjIFVzaW5nIGRpZmZlcmVudCBqb2luIHR5cGVzIGluIGFuYWx5c2luZyB5b3VyIGRhdGEKCiogSW4gbWFueSBjYXNlcyB0aGUgZGF0YSB5b3UgaGF2ZSBpbiB5b3VyIHRhYmxlcyBtYXkgaGF2ZSBjb21lIGZyb20gZGlzcGVyYXRlIHNvdXJjZXMsIGluIHRoYXQgdGhleSBkbyBub3QgZm9ybSBwYXJ0IG9mIGEgcGxhbm5lZCByZWxhdGlvbmFsIGRhdGFiYXNlLiAKKiBJdCBoYXMgYmVlbiB5b3VyIGRlY2lzaW9uIHRvIGJyaW5nIHRvZ2V0aGVyIChqb2luKSB0aGUgZGF0YSBpbiB0aGUgdGFibGVzLgoKKiBJbiBvcmRlciB0byBkbyB0aGlzIGF0IGFsbCB5b3UgbXVzdCBiZSBjb25maWRlbnQgdGhhdCB0aGUgdGFibGVzIG9mIGRhdGEgZG8gaGF2ZSBjb2x1bW5zIHdoaWNoIGhhdmUgYSBjb21tb24gc2V0IG9mIHZhbHVlcyB0aGF0IHlvdSBjYW4gam9pbiBvbi4KCiogQXNzdW1pbmcgeW91IGRvIGhhdmUgYSBjb21tb24gY29sdW1uIHRvIGpvaW4gb24sIHlvdSBjYW4gdXNlIGFuIGBJbm5lciBqb2luYCB0byBjb21iaW5lIHRoZSBkYXRhLgoKKiBIb3dldmVyIGl0IHdpbGwgYWxzbyBiZSBpbXBvcnRhbnQgZm9yIHlvdSB0byBlc3RhYmxpc2ggcm93cyBpbiBib3RoIG9mIHRoZSB0YWJsZXMgZm9yIHdoaWNoIHRoZXJlIGlzIG5vIG1hdGNoaW5nIHJvdyBpbiB0aGUgb3RoZXIgdGFibGUuCgogICAgKiBZb3UgbWF5IGV4cGVjdCBzb21lIHRvIGJlIG1pc3NpbmcKICAgICogWW91IG1heSBub3QgY2FyZSB0aGF0IHNvbWUgYXJlIG1pc3NpbmcKICAgICogWW91IG1heSBuZWVkIHRvIGV4cGxhaW4gd2h5IHNvbWUgYXJlIG1pc3NpbmcKCiogVG8gZG8gdGhpcyB5b3Ugd2lsbCB3YW50IHRvIHVzZSBhIGBGdWxsIG91dGVyIGpvaW5gIG9yIGluIHRoZSBjYXNlIG9mIFNRTGl0ZSBhIGBMZWZ0IG91dGVyIGpvaW5gIHJ1biB0d2ljZSB1c2luZyBib3RoIHRhYmxlcyBpbiB0aGUgYEZyb21gIGFuZCBgSm9pbmAgY2xhdXNlcy4KCiogVG8gaWxsdXN0cmF0ZSB0aGUgZGlmZmVyZW50IGpvaW4gdHlwZXMgd2Ugd2lsbCB1c2UgdHdvIHNtYWxsIGV4YW1wbGUgdGFibGVzCgohW2ltYWdlXShpbWFnZXMvam9pbmV4YW1wbGUxLnBuZykKKiBUaGVzZSB0YWJsZXMgaGF2ZSBiZWVuIGluY2x1ZGVkIGluIHRoZSBTTjc1NzcgZGF0YWJhc2UKCiFbaW1hZ2VdKGltYWdlcy9pbm5lcmpvaW4ucG5nKQohW2ltYWdlXShpbWFnZXMvbGVmdG91dGVyam9pbi5wbmcpCiFbaW1hZ2VdKGltYWdlcy9sZWZ0b3V0ZXJqb2lucmV2ZXJzZWQucG5nKQoKKiBJbiB0aGUgdHdvIE91dGVyIHF1ZXJpZXMgREJCcm93c2VyIHNob3dzIHRoZSBOVUxMIHZhbHVlcyBhcyByZWQgY2VsbHMuCgojIyMgRXhlcmNpc2UKMS4gTW9kaWZ5IHRoZSBmaXJzdCBgTGVmdCBPdXRlciBKb2luYCBxdWVyeSBhYm92ZSBzbyB0aGF0IG9ubHkgdGhlIGpvaW5lZCByb3dzIHdoZXJlIHRoZXJlIGlzIG5vIG1hdGNoIGluIHRoZSBBbmltYWxzX0VhdCB0YWJsZSBhcmUgcmV0dXJuZWQuCgpgYGBzcWwKU0VMRUNUIGEuKiwgZS4qCkZST00gQW5pbWFscyBhcyBhCkxFRlQgT1VURVIgSk9JTiBBbmltYWxzX0VhdCBhcyBlCm9uIGEuSURfQSA9IGUuSURfRQpgYGAKCjIuIE1vZGlmeSB0aGUgc2Vjb25kIGBMZWZ0IE91dGVyIEpvaW5gIHF1ZXJ5IGFib3ZlIHNvIHRoYXQgb25seSB0aGUgdGhlIGBJZF9FIGNvbHVtbmAgZnJvbSB0aGUgYEFuaW1hbHNfRWF0IHRhYmxlYCBpcyByZXR1cm5lZCB3aGVyZSB0aGVyZSBpcyBubyBtYXRjaGluZyByb3cgaW4gdGhlIEFuaW1hbCB0YWJsZS4KCmBgYHNxbApTRUxFQ1QgYS4qLCBlLioKRlJPTSBBbmltYWxzX0VhdCBhcyBhCkxFRlQgT1VURVIgSk9JTiBBbmltYWxzIGFzIGEKb24gYS5JRF9BID0gZS5JRF9FCmBgYAoKIyMjI1NvbHV0aW9uOgpgYGBzcWwKU0VMRUNUIGEuKiAsIGUuKgpGUk9NIEFuaW1hbHMgIGFzIGEKTGVmdCBvdXRlciBKb2luICBBbmltYWxzX0VhdCBhcyBlCm9uICBhLklkX0EgPSBlLklkX0UKd2hlcmUgZS5JZF9lIGlzIE5VTEw7CmBgYAoKYGBgc3FsClNFTEVDVCBJZF9FCkZST00gQW5pbWFsc19FYXQKTGVmdCBvdXRlciBKb2luIEFuaW1hbHMKT04gIElkX0EgPSBJZF9FCldIRVJFIElkX0EgaXMgTlVMTApPUkRFUiBieSBJZF9FOwpgYGAKQmVjYXVzZSB0aGVyZSBpcyBubyBjb25mbGljdCBpbiB0aGUgY29sdW1uIG5hbWVzIGFjcm9zcyB0aGUgdHdvIHRhYmxlcywgd2UgaGF2ZSBjaG9zZW4gbm90IHRvIHVzZSBhbGlhc+KAmS4gTm90aWNlIHRoYXQgdGhlIElkX0EgY29sdW1uIHdoaWNoIHdlIGFyZSBjaGVja2luZyBmb3IgTlVMTCBkb2VzbuKAmXQgaGF2ZSB0byBiZSBhIHJldHVybmVkIGNvbHVtbi4KCgoKIyMjIyBrZXkgcG9pbnRzCgoqIEpvaW5zIGFyZSB1c2VkIHRvIGNvbWJpbmUgZGF0YSBmcm9tIHR3byBvciBtb3JlIHRhYmxlcy4KCiogVGFibGVzIHRvIGJlIGpvaW5lZCBtdXN0IGhhdmUgYSBjb2x1bW4gaW4gZWFjaCB3aGljaCByZXByZXNlbnQgdGhlIHNhbWUgdGhpbmcKCiogVGhlcmUgYXJlIHNldmVyYWwgZGlmZmVyZW50IHR5cGVzIG9mIGpvaW5zCgoqIFRoZSBJbm5lciBqb2luIGlzIHRoZSBtb3N0IGNvbW1vbmx5IHVzZQoKKiBZb3UgbWF5IGhhdmUgdG8gdXNlIHRoZSBvdGhlciBqb2luIHR5cGVzIHRvIGRpc2NvdmVyIG1pc3NpbmcgZGF0YSBvciBnYXBzIGluIHlvdXIgZGF0YQoKCgoKCgoKCgoKCgo=