Skip to content

Commit

Permalink
docs: Add token caching and query result information to docsrc/Connec…
Browse files Browse the repository at this point in the history
…ting_and_queries.rst (#278)
  • Loading branch information
pauls-FB authored Oct 10, 2023
1 parent 7e1942f commit a38d196
Showing 1 changed file with 82 additions and 11 deletions.
93 changes: 82 additions & 11 deletions docsrc/Connecting_and_queries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,32 @@ To get started, follow the steps below:
) as connection:
cursor = connection.cursor()

**3. Execute commands using the cursor**

**3. Token management/caching**

Firebolt allows access by using authentication and refresh tokens. In order to authenticate,
the SDK issues an http login request to the Firebolt API, providing username and password.
The API returns an authentication token and refresh token. Authentication tokens are valid
for 12 hours, and can be refreshed using the refresh token. The SDK uses the authentication
token for all subsequent requests, and includes logic for refreshing the token if it is reported as expired.

Because a typical script that uses the SDK usually runs for less than a minute and then is closed,
the token is lost because it’s only stored in a process memory. To avoid that, the SDK by default does token caching.
Token caching is designed to preserve the token in filesystem to later reuse it for requests and save time on
authentication api request. It also helps for workflows that use the SDL in parallel or in sequential scripts
on the same machine, as only a single authentication request is performed. The caching works by preserving the
token value and it’s expiration timestamp in filesystem, in user data directory. On the authentication, the SDK
first tries to find a token cache file and, if it exists, checks that token is not yet expired. If the token
is valid, it’s used for further authorization. The token value itself is encrypted with PBKDF2 algorithm,
the encryption key is a combination of user credentials.

Token caching can be disabled if desired. If the server the SDK is running on has a read only
filesystem (when using AWS Lambda, for example), then the SDK will not be able to store the token.
The caching is disabled by adding ``use_token_cache=False`` to the auth object. From the examples above,
it would look like: ``auth=UsernamePassword(username, password,use_token_cache=False),``


**4. Execute commands using the cursor**

The ``cursor`` object can be used to send queries and commands to your Firebolt
database and engine. See below for examples of functions using the ``cursor`` object.
Expand Down Expand Up @@ -168,7 +193,7 @@ queries. For help, see :ref:`managing_resources:starting an engine`.
For reference documentation on ``cursor`` functions, see :ref:`cursor <firebolt.db:cursor>`.


Fetching query results
Fetching query results
-----------------------

After running a query, you can fetch the results using a ``cursor`` object. The examples
Expand All @@ -177,23 +202,69 @@ below use the data queried from ``test_table`` created in the

.. _fetch_example:

::
::
print(cursor.fetchone())
**Returns**: ``[2, 'world']``

::
print(cursor.fetchmany(2))
**Returns**: ``[[1, 'hello'], [3, '!']]``

::
print(cursor.fetchall())
**Returns**: ``[[2, 'world'], [1, 'hello'], [3, '!']]``

::
print(cursor.fetchall())
**Returns**: ``[[2, 'world'], [1, 'hello'], [3, '!']]``

Fetching query result information
-----------------------

print(cursor.fetchone())
After running a query, you can fetch information about the results using the same ``cursor`` object. The examples
below are from the last SELECT query in :ref:`connecting_and_queries:Inserting and selecting data`.

**Returns**: ``[2, 'world']``
.. _result_information_example:

::
**rowcount**

print(cursor.fetchmany(2))
- For a SELECT query, rowcount is the number of rows selected.
- For An INSERT query, it is always -1.
- For DDL (CREATE/DROP), it is always 1

**Returns**: ``[[1, 'hello'], [3, '!']]``
::
print("Rowcount: ", cursor.rowcount)

::
**Returns**: ``Rowcount: 3``


**description**

description is a list of Column objects, each one responsible for a single column in a result set. Only name and type_code fields get populated, all others are always empty.

- name is the name of the column.
- type_code is the data type of the column. It can be:

- a python type (int, float, str, date, datetime)
- an ARRAY object, that signifies a list of some type. The inner type can is stored in ``.subtype`` field
- a DECIMAL object, that signifies a decimal value. It’s precision and scale are stored in ``.precision`` and ``.scale`` fields
- a DATETIME64 object, that signifies a datetime value with an extended precision. The precision is stored in ``.precision``

::
print("Description: ", cursor.description)

print(cursor.fetchall())
**Returns**: ``Description: [Column(name='id', type_code=<class 'int'>, display_size=None, internal_size=None, precision=None, scale=None, null_ok=None), Column(name='name', type_code=<class 'str'>, display_size=None, internal_size=None, precision=None, scale=None, null_ok=None)]``

**Returns**: ``[[2, 'world'], [1, 'hello'], [3, '!']]``


Executing parameterized queries
Expand Down

0 comments on commit a38d196

Please sign in to comment.