Alation Analytics Object Queries¶
Note
These queries are for Alation Analytics Version 1 (V1).
Almost everything in Alation is an Alation Object. Alation Objects are stored in table public.alation_object. For descriptions of Alation Analytics metadata, refer to Alation Analytics Metadata Descriptions.
Objects Types¶
Alation Objects are characterized by type. Each Object Type has an ID in AA. Some important object types and their IDs are:
Object Type |
Object Type ID |
---|---|
Data Source |
7 |
Schema |
23 |
Table |
27 |
Column |
1 |
Article |
0 |
To find out all object types by frequency from AA, you can run the following query:
Object Types By Frequency¶
SELECT
object_type_name,
O.object_type_id,
count(1) AS freq
FROM
public.alation_object AS O
JOIN public.alation_object_type AS OT ON OT.object_type_id = O.object_type_id
-- so we can use the object type by name
GROUP BY
object_type_name,
O.object_type_id
ORDER BY
freq DESC;
Querying Objects¶
If you are interested in values for a specific object, you should filter by its Object Type. The field values of Alation objects are stored in table public.field_value.
For example, the sample query below retrieves all Tables in Alation and available Fields.
All Tables and Their Fields¶
-- we want to see all fields belonging to tables:
SELECT
object_url,
field_name,
count(1) AS freq
FROM
public.object_field_value AS OFV
JOIN public.object_field AS OF ON OFV.field_id = OF.field_id
-- so we can use the field name
JOIN public.alation_object_type AS OT ON OT.object_type_id = OFV.object_type_id
-- so we can use the object type by name
JOIN public.field_value AS FV ON FV.value_fp = OFV.value_fp
-- so we can get the field value
JOIN public.alation_object AS O ON O.object_uuid = OFV.object_uuid
AND O.object_type_id = OFV.object_type_id -- so we can get the object URL
WHERE
object_type_name = 'table' -- because the object_uuid is not global
GROUP BY
object_url,
field_name
ORDER BY
object_url;
However, the query above does not pull all custom fields. There are some custom fields that use HSTORE data type and are stored in the hstore_value field. The HSTORE fields need to be accessed as shown in the sample query below.
Custom HSTORE Fields for Tables¶
-- display which "normal" custom fields are filled for Alation objects of a certain type
SELECT
OFV.field_id,
field_name,
count(1) AS filled,
'normal' AS origin
FROM
public.object_field_value OFV
JOIN public.object_field AS OF on OFV.field_id = OF.field_id
--so we can use the field name
WHERE
OFV.object_type_id = 27
/* table */
GROUP BY
OFV.field_id,
field_name
UNION
/* combine the two datasets */
-- display which "hstore-" custom fields are filled
SELECT
custom_fields.field_id,
field_name,
count(1) AS filled,
'hstore' AS origin
FROM
(
SELECT
(each(hstore_value)).key :: int AS field_id,
(each(hstore_value)).value AS output
FROM
public.object_field_value OFV
JOIN public.field_value AS FV ON FV.value_fp = OFV.value_fp
-- so we can get the field value
WHERE
OFV.object_type_id = 27
/* table */
AND OFV.field_id = 3048
/* custom field values */
) custom_fields
JOIN public.object_field AS OF ON custom_fields.field_id = OF.field_id
-- so we can use the field name
GROUP BY
custom_fields.field_id,
field_name
This query joins several tables so that the analyst can more easily interpret the output and change the query.
Identifying Objects¶
An Object in Alation can be addressed in different ways, depending on context. For example, a Table can be identified in several different ways:
Identification |
Example |
Comment |
---|---|---|
URL |
/table/1810/ |
Used for finding an object in the UI |
table_id in API call |
1810 |
Used for the Catalog API |
UUID in Alation |
00000000-0000-0 |
ID in |
Analytics |
000-0000-00000000013d |
public.alation_object Identical in value (not format) to numerical ID in URL |
name |
alation_object |
Technical name in the database |
key |
public.alation_object |
Key format used in Alation data dictionaries |
@-mention |
<a data-oid=”1810” data-otype=”table” href=”/table/1810/”> |
Used to create the active hyperlinks in Alation |
The most efficient way to identify an Object in AA is the UUID, but it may be more practical to use other ways of identifying the Object. It is useful to understand how to look up the other identifiers.
Obtaining Title and Description¶
You can build a query that shows names, titles, and descriptions for our tables. This query is complex because the fields appear as rows, and we need to “pivot” them using the CASE technique.
Titles and Descriptions For Tables¶
-- we want to see certain fields and values belonging to tables:
SELECT
object_url,
MAX(CASE WHEN field_name = 'name' THEN text_value END) AS name,
MAX(CASE WHEN field_name = 'title' THEN text_value END) AS title,
MAX(
CASE WHEN field_name = 'schema_original_name' THEN text_value END
) AS schema,
MAX(
CASE WHEN field_name = 'description' THEN text_value END
) AS description
FROM
public.object_field_value AS OFV
JOIN public.object_field AS OF ON OFV.field_id = OF.field_id
-- so we can use the field name
JOIN public.alation_object_type AS OT ON OT.object_type_id = OFV.object_type_id
-- so we can use the object type by name
JOIN public.field_value AS FV ON FV.value_fp = OFV.value_fp
-- so we can get the field value
JOIN public.alation_object AS O ON O.object_uuid = OFV.object_uuid
AND O.object_type_id = OFV.object_type_id
WHERE
object_type_name = 'table' -- because the object_uuid is not global
GROUP BY
object_url;
Getting Children and Parents¶
There is a parent - child relationship for many objects in Alation: Data
Source->Schema->Table->Column. These relationships are stored in
table public.object_parent_relationship
.
You can create a hierarchical list of all columns in Alation, starting at the Data Source level. All of the relevant UUIDs can be found with the following query:
Table Objects Hierarchy¶
-- get the full data dictionary out of alation
SELECT
column_id,
MAX(
CASE WHEN parent_object_type_id = 27 THEN parent_object_uuid :: text END
) AS table_id,
MAX(
CASE WHEN parent_object_type_id = 23 THEN parent_object_uuid :: text END
) AS schema_id,
MAX(
CASE WHEN parent_object_type_id = 7 THEN parent_object_uuid :: text END
) AS ds_id
FROM
(
SELECT
object_uuid AS column_id,
object_url AS column_url
FROM
public.alation_object
WHERE
object_type_id = 1
/* column */
) columns
JOIN public.object_parent_relationship AS OP ON OP.object_uuid = columns.column_id
AND OP.object_type_id = 1
GROUP BY
column_id;
Custom HSTORE Fields For Articles¶
Custom fields that are stored inside an HSTORE value need to be unpacked with Postgres.
Retrieving Custom Fields For Articles¶
-- display which "normal" custom fields are filled for Alation objects of a certain type
SELECT
OFV.field_id,
field_name,
count(1) AS filled,
'normal' AS origin
FROM
public.object_field_value OFV -- to get object_url
-- JOIN public.alation_object AS O ON O.object_uuid = OFV.object_uuid
-- AND O.object_type_id = OFV.object_type_id
JOIN public.object_field AS OF ON OFV.field_id = OF.field_id -- so we can use the field name
WHERE
OFV.object_type_id = 0
/* article */
GROUP BY
OFV.field_id,
field_name
UNION
/* combine the two datasets */
-- display which "hstore-" custom fields are filled
SELECT
custom_fields.field_id,
field_name,
count(1) AS filled,
'hstore' AS origin
FROM
(
SELECT
(each(hstore_value)).key :: int AS field_id,
(each(hstore_value)).value AS output
FROM
public.object_field_value OFV -- to get object_url
-- JOIN public.alation_object AS O ON O.object_uuid =
OFV.object_uuid -- AND O.object_type_id = OFV.object_type_id
JOIN public.field_value AS FV ON FV.value_fp = OFV.value_fp
-- so we can get the field value
WHERE
OFV.object_type_id = 0
/* article */
AND OFV.field_id = 3048
/* custom field values */
) custom_fields
JOIN public.object_field AS OF ON custom_fields.field_id = OF.field_id
-- so we can use the field name
GROUP BY
custom_fields.field_id,
field_name
If the custom field has a user, it needs to be joined from the user table.
Joining Users¶
WITH custom_field_values AS (
SELECT
object_uuid,
field_name,
field_datatype,
output
FROM
(
SELECT
ofv.object_uuid,
(each(hstore_value)).key :: int AS field_id,
(each(hstore_value)).value AS output
FROM
public.object_field_value AS OFV
JOIN public.field_value AS FV ON FV.value_fp = OFV.value_fp
-- so we can get the field value
JOIN public.alation_object AS O ON O.object_uuid = OFV.object_uuid
AND O.object_type_id = OFV.object_type_id -- to get object_url
WHERE
OFV.field_id = 3048
/* custom field values */
AND OFV.object_type_id = 0
/* article */
) T
INNER JOIN public.object_field AS OF ON T.field_id = OF.field_id
)
SELECT
object_uuid AS article_id,
oid AS user_id,
display_name,
email
FROM
(
SELECT
object_uuid,
kv :: json ->> 'otype' AS otype,
kv :: json ->> 'oid' AS oid,
kv
FROM
(
SELECT
object_uuid,
field_name,
json_array_elements(output :: json) AS kv
FROM
custom_field_values
WHERE
field_datatype = 'OBJECT_SET'
) KV
) Users
INNER JOIN public.alation_user AU ON AU.user_id = oid :: int
WHERE
otype = 'user'
GROUP BY
1,
2,
3,
4
ORDER BY
object_uuid;