Starburst OpenAPI connector#
Note
The Starburst OpenAPI connector is available as a public preview in Starburst Enterprise. Contact Starburst account team with questions or feedback.
The Starburst OpenAPI connector reads an OpenAPI description and automatically creates table functions that provide access to data available only through HTTP APIs. An OpenAPI description is a standard, language-agnostic interface to HTTP APIs that lets both humans and computers discover and understand the capabilities of a service.
Requirements#
To use the Starburst OpenAPI connector, you need:
A SEP 482-e or later cluster.
An OpenAPI description, version 3.0.x or earlier, provided as a file or a URL.
A valid Starburst Enterprise license.
Configuration#
Before you configure the connector, you need the following details:
The location of the OpenAPI description, specified with the
openapi.description-locationproperty. The location can be a file path or a URL, and it must be accessible by all coordinator and worker nodes. For example,/etc/starburst/specification.yamlorhttps://petstore3.swagger.io/api/v3/openapi.yaml.The base URI that the connector prepends to the path items in the OpenAPI description, specified with the
openapi.base-uriproperty. For example, to access an API athttps://api.dictionaryapi.dev/api/v2/entries/en/wordwhen the OpenAPI description defines the path/entries/en/{word}, set the base URI tohttps://api.dictionaryapi.dev/api/v2.
To configure the connector, create a catalog properties file that
specifies the Starburst OpenAPI connector by setting the connector.name to
starburst_openapi.
connector.name=starburst_openapi
openapi.description-location=/etc/starburst/specification.yaml
openapi.base-uri=https://petstore3.swagger.io/api/v3
The connector has the following configuration properties:
Property name |
Description |
Default |
|---|---|---|
|
Path or URL to the OpenAPI description. The location must be accessible by all coordinator and worker nodes. Required. |
|
|
Base URI that the connector prepends to the path items defined in the OpenAPI description. Required. |
|
|
Determines how the connector handles response fields and table function parameters that do not have a supported type conversion. See Trino type mapping for the available values. |
|
|
Pagination style used by the API to split large responses across multiple pages. See Pagination for the available values and their additional properties. |
|
Secrets#
The connector supports two types of configurable secrets for authenticating to the HTTP API.
API key secrets#
To write a static secret to a header, query parameter, or cookie, set
openapi.security-scheme.type to apikey and configure the following
properties:
Property name |
Description |
|---|---|
|
OpenAPI security
type. Set to
|
|
Location of the secret. Set to |
|
Name of the header, query parameter, or cookie that carries the secret. |
|
Value of the secret. |
For example, to pass a secret in a header named X-Api-Key, add the following
to the catalog:
openapi.security-scheme.type=apikey
openapi.security-scheme.in=header
openapi.security-scheme.name=X-Api-Key
openapi.security-scheme.secret=MY_SECRET_KEY
OAuth 2.0 client credentials#
To have the connector participate in an OAuth 2.0 client credentials
flow, set
openapi.security-scheme.type to oauth2 and configure the following
properties:
Property name |
Description |
|---|---|
|
OpenAPI security
type. Set to
|
|
URL of the token endpoint used to request an access token. |
|
Client ID used to authenticate to the token endpoint. |
|
Client secret used to authenticate to the token endpoint. |
|
Comma-separated list of scopes to request. |
For example:
openapi.security-scheme.type=oauth2
openapi.security-scheme.token-url=https://example.org/token
openapi.security-scheme.client-id=MY_CLIENT_ID
openapi.security-scheme.client-secret=MY_CLIENT_SECRET
openapi.security-scheme.scopes=comma,separated,list
Pagination#
Many HTTP APIs split large responses into pages and provide a mechanism to
request the next page until all results are returned. Because the OpenAPI
standard does not define a way to describe pagination, you must tell the
connector which pagination style the API uses. Set the openapi.pagination
property to one of the following values:
Style |
Description |
|---|---|
|
Default. The connector does not paginate and requires no additional configuration. |
|
The connector requests each page with an offset parameter. |
|
The connector requests each page by page number. |
|
The connector follows the link labeled |
|
The connector reads an opaque cursor from a field in the response body and passes it as a query parameter to request the next page. |
|
The connector reads a cursor from a field on the last element of each page and passes it to request the next page. |
|
The connector reads the absolute URL of the next page from a field in the response body. |
Offset pagination#
When openapi.pagination is set to offset, configure the following
properties:
Property name |
Description |
|---|---|
|
Name of the request parameter that the connector sets to the offset. |
|
JSON pointer to the response array whose last element provides the next
cursor, for example |
Page number pagination#
When openapi.pagination is set to page_number, configure the following
properties:
Property name |
Description |
|---|---|
|
Name of the request parameter that the connector sets to the page number. |
|
JSON pointer to the boolean field in the response body that indicates
whether the last page has been reached, for example |
Next cursor field pagination#
When openapi.pagination is set to next_cursor_field, configure the following
properties:
Property name |
Description |
|---|---|
|
Query parameter name for the pagination cursor. |
|
JSON pointer to the field in the response body that contains the next
cursor, for example |
Last element cursor field pagination#
When openapi.pagination is set to last_element_cursor_field, configure the
following property:
openapi.pagination.last-element-cursor-field.cursor-parameter-name: Parameter name used to pass the cursor to the next page request. The cursor is taken from a field on the last element of the current page.
Next URL field pagination#
When openapi.pagination is set to next_url_field, configure the following
property:
openapi.pagination.next-url-cursor.next-url-field-json-pointer: JSON pointer to the field in the response body that contains the absolute URL for the next page, for example/paging/next.
Table functions#
After you configure a catalog with an OpenAPI description, the connector automatically transforms the API paths into table functions. Use the SHOW FUNCTIONS statement to list the available table functions, and call them with the TABLE syntax to query the API. See Example for a walkthrough.
Unsupported paths#
The connector does not map the following paths to table functions:
The
/path.Paths without a
GEToperation.Paths without an expected successful status code.
Paths with a successful status code that do not return a JSON response with a defined
schema.
The connector provides an error message for all other unsupported paths.
System table#
The connector exposes a system metadata table called system.table_functions
that you can query for richer metadata about the available table functions.
Each row includes the function name, the API path it maps to, its description,
and its input and output columns. Use the table to discover the available
table functions and inspect their schemas without preparing a statement for each
one.
SELECT * FROM example.system.table_functions;
function_name | api_path | description | input_columns | output_columns
--------------------+-------------------+----------------------+-----------------------------------------------+-------------------------------
pet_find_by_status | /pet/findByStatus | Finds Pets by status.| [{name=status, type=varchar, required=false}] | [{name=id, type=bigint}, ...]
pet_pet_id | /pet/{petId} | Find pet by ID. | [{name=petId, type=bigint, required=true}] | [{name=id, type=bigint}, ...]
store_inventory | /store/inventory | Returns inventories. | NULL | [{name=..., type=...}, ...]
Trino type mapping#
The connector automatically maps the schema of the response data to the best supported Trino type. The connector applies the following mappings:
JSON arrays are mapped to ARRAY types. Use the UNNEST syntax to expand an array into separate rows for further processing.
JSON objects are mapped to ROW types. Use the field reference operator to access individual fields.
JSON booleans are mapped to the BOOLEAN type.
JSON numbers and strings are mapped to Trino types based on their OpenAPI format, as described in the following sections. An OpenAPI format specifies how to interpret a raw JSON value.
Number type mapping#
The connector maps JSON numbers to Trino types based on the following OpenAPI formats:
OpenAPI format |
Trino type |
|---|---|
No format |
A NUMBER type with unlimited precision, because the JSON grammar allows numbers to have unlimited precision. |
|
|
|
String type mapping#
The connector maps JSON strings to Trino types based on the following OpenAPI formats:
OpenAPI format |
Trino type |
|---|---|
No format |
Unbounded VARCHAR |
|
|
|
|
|
|
|
TIMESTAMP(12) WITH TIME ZONE, with picosecond precision. Any digits more precise than picoseconds are dropped. |
Unsupported type conversions#
When a response field or table function parameter does not have a supported type
conversion, the openapi.cast-policy property controls how the connector
behaves:
Value |
Description |
|---|---|
|
The connector raises an error for each field or parameter that does not have a supported conversion. |
|
The connector drops fields or parameters that do not have a supported conversion. If a field or parameter cannot be dropped, the connector drops the affected table function. |
|
The connector converts unsupported fields or parameters to a fallback type, such as JSON, VARCHAR, or NUMBER. Because the connector maps values to their natural Trino type as format support improves, table function schemas that rely on fallback types can change between releases. |
You can inspect the resulting types with a prepared
statement and the DESCRIBE OUTPUT statement, or by querying the
system table, as shown in Example.
Example#
The following example uses a catalog named dictionary that is configured to
access a public dictionary API:
connector.name=starburst_openapi
openapi.description-location=https://api.dictionaryapi.dev/openapi.yaml
openapi.base-uri=https://api.dictionaryapi.dev/api/v2
Use the SHOW FUNCTIONS statement to list the available table functions:
SHOW FUNCTIONS IN dictionary.default;
Function | Return Type | Argument Types | Function Type | Deterministic | Description
-----------------------+-------------+------------------+---------------+---------------+-------------
entries_en_word | unknown | varchar, varchar | table | false |
(1 row)
The connector maps the /entries/en/{word} path item of the OpenAPI description
to the entries_en_word table function. This API takes one
parameter,
word, which the connector maps to a table function argument. Pass the argument
to query the API:
SELECT word, phonetic
FROM TABLE(dictionary.default.entries_en_word(
WORD => 'lead'
));
word | phonetic
------+----------
lead | /lɛd/
lead | /liːd/
To inspect the types that the connector maps from the response schema, use a
prepared statement with the DESCRIBE OUTPUT statement:
PREPARE my_select FROM
SELECT *
FROM TABLE(dictionary.default.entries_en_word(
WORD => 'star'
));
DESCRIBE OUTPUT my_select;
Column Name | Catalog | Schema | Table | Type
-------------+---------+--------+-------+------------------------------------------------------------------
meanings | | | | array(row("definitions" array(row("antonyms" array(varchar), ...
origin | | | | varchar
phonetic | | | | varchar
phonetics | | | | array(row("audio" varchar, "text" varchar))
word | | | | varchar
Alternatively, query the system.table_functions table
to retrieve the output column types in a single query, without preparing a
statement:
SELECT output_column.name, output_column.type
FROM dictionary.system.table_functions
CROSS JOIN UNNEST(output_columns) AS output_column
WHERE function_name = 'entries_en_word';
The following is the type of the meanings column, with adjusted whitespace for
clarity:
array(
row(
"definitions" array(
row(
"antonyms" array(varchar),
"definition" varchar,
"example" varchar,
"synonyms" array(varchar)
)
),
"partofspeech" varchar
)
)
The connector maps JSON arrays to ARRAY types. Use the UNNEST syntax to expand these arrays for further processing:
SELECT antonym
FROM TABLE(dictionary.default.entries_en_word(
WORD => 'antonym'
))
CROSS JOIN UNNEST(meanings)
CROSS JOIN UNNEST(definitions)
CROSS JOIN UNNEST(antonyms) AS t(antonym)
WHERE antonym IS NOT NULL;
In the following output, antonym is an unbounded
VARCHAR, the default type for unformatted strings:
antonym
---------
synonym
The connector maps JSON objects to ROW types. Use the field reference operator to access individual fields:
SELECT meaning.partofspeech, definition_entry.definition
FROM TABLE(dictionary.default.entries_en_word(
WORD => 'laconic'
)) AS response
CROSS JOIN UNNEST(response.meanings) AS meaning
CROSS JOIN UNNEST(definitions) AS definition_entry;
partofspeech | definition
--------------+----------------------------------------------------
adjective | Using as few words as possible; pithy and concise.