Skip to content

Commit a38d196

Browse files
authored
docs: Add token caching and query result information to docsrc/Connecting_and_queries.rst (#278)
1 parent 7e1942f commit a38d196

File tree

1 file changed

+82
-11
lines changed

1 file changed

+82
-11
lines changed

docsrc/Connecting_and_queries.rst

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,32 @@ To get started, follow the steps below:
116116
) as connection:
117117
cursor = connection.cursor()
118118

119-
**3. Execute commands using the cursor**
119+
120+
**3. Token management/caching**
121+
122+
Firebolt allows access by using authentication and refresh tokens. In order to authenticate,
123+
the SDK issues an http login request to the Firebolt API, providing username and password.
124+
The API returns an authentication token and refresh token. Authentication tokens are valid
125+
for 12 hours, and can be refreshed using the refresh token. The SDK uses the authentication
126+
token for all subsequent requests, and includes logic for refreshing the token if it is reported as expired.
127+
128+
Because a typical script that uses the SDK usually runs for less than a minute and then is closed,
129+
the token is lost because it’s only stored in a process memory. To avoid that, the SDK by default does token caching.
130+
Token caching is designed to preserve the token in filesystem to later reuse it for requests and save time on
131+
authentication api request. It also helps for workflows that use the SDL in parallel or in sequential scripts
132+
on the same machine, as only a single authentication request is performed. The caching works by preserving the
133+
token value and it’s expiration timestamp in filesystem, in user data directory. On the authentication, the SDK
134+
first tries to find a token cache file and, if it exists, checks that token is not yet expired. If the token
135+
is valid, it’s used for further authorization. The token value itself is encrypted with PBKDF2 algorithm,
136+
the encryption key is a combination of user credentials.
137+
138+
Token caching can be disabled if desired. If the server the SDK is running on has a read only
139+
filesystem (when using AWS Lambda, for example), then the SDK will not be able to store the token.
140+
The caching is disabled by adding ``use_token_cache=False`` to the auth object. From the examples above,
141+
it would look like: ``auth=UsernamePassword(username, password,use_token_cache=False),``
142+
143+
144+
**4. Execute commands using the cursor**
120145

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

170195

171-
Fetching query results
196+
Fetching query results
172197
-----------------------
173198

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

178203
.. _fetch_example:
179204

180-
::
205+
::
206+
207+
print(cursor.fetchone())
208+
209+
**Returns**: ``[2, 'world']``
210+
211+
::
212+
213+
print(cursor.fetchmany(2))
214+
215+
**Returns**: ``[[1, 'hello'], [3, '!']]``
216+
217+
::
218+
219+
print(cursor.fetchall())
220+
221+
**Returns**: ``[[2, 'world'], [1, 'hello'], [3, '!']]``
222+
223+
::
224+
225+
print(cursor.fetchall())
226+
227+
**Returns**: ``[[2, 'world'], [1, 'hello'], [3, '!']]``
228+
229+
Fetching query result information
230+
-----------------------
181231

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

184-
**Returns**: ``[2, 'world']``
235+
.. _result_information_example:
185236

186-
::
237+
**rowcount**
187238

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

190-
**Returns**: ``[[1, 'hello'], [3, '!']]``
243+
::
244+
245+
print("Rowcount: ", cursor.rowcount)
191246

192-
::
247+
**Returns**: ``Rowcount: 3``
248+
249+
250+
**description**
251+
252+
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.
253+
254+
- name is the name of the column.
255+
- type_code is the data type of the column. It can be:
256+
257+
- a python type (int, float, str, date, datetime)
258+
- an ARRAY object, that signifies a list of some type. The inner type can is stored in ``.subtype`` field
259+
- a DECIMAL object, that signifies a decimal value. It’s precision and scale are stored in ``.precision`` and ``.scale`` fields
260+
- a DATETIME64 object, that signifies a datetime value with an extended precision. The precision is stored in ``.precision``
261+
262+
::
263+
264+
print("Description: ", cursor.description)
193265

194-
print(cursor.fetchall())
266+
**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)]``
195267

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

198269

199270
Executing parameterized queries

0 commit comments

Comments
 (0)